Counting percent of rows with category out of total number of rows using Dynamic Linq

后端 未结 1 516
刺人心
刺人心 2020-12-12 07:24

How to achieve this using Dynamic Linq Join and Dynamic Linq SelectMany

相关标签:
1条回答
  • 2020-12-12 07:31

    Desired result is in q and q2.
    q shows combination of aggregates from different levels of grouping in one expression.
    q2 uses calculated agg from prev levels and generates shorter SQL query.

    var grp=(db.A as IQueryable).GroupBy("grp","it");
    var grp2=grp.Select("new(key as key,new(count() as cnt) as agg)");
    foreach(dynamic r in grp2) Console.WriteLine("grp:"+r.key+"\tcnt:"+r.agg.cnt);
    //foreach(dynamic r in grp) Console.WriteLine(r.Key+"\t"+r.Count()); // throws RuntimeBinderException
    Console.WriteLine("----------------------");
    var cat=(db.A as IQueryable)
        .SelectMany("B","new(outer as a,inner as b)")
        .GroupBy("new(a.grp,b.cat)","it");
    var cat2=cat.Select("new(key as key,new(count() as cnt) as agg)");
    foreach(dynamic r in cat2) Console.WriteLine("grp:"+r.key.grp+"\tcat:"+r.key.cat+"\tcnt:"+r.agg.cnt);
    
    Console.WriteLine("----------- result -----------");
    var q=cat.Join("c",grp,"g","c.key.grp","g.key","new(g.key as grp,c.key.cat,new(c.count()*100/g.count() as percent) as agg)");
    foreach(dynamic r in q) Console.WriteLine("grp:"+r.grp+"\tcat:"+r.cat+"\tpercent:"+r.agg.percent);
    Console.WriteLine("----------- result2 -----------");
    var q2=cat2.Join("c",grp2,"g","c.key.grp","g.key","new(g.key as grp,c.key.cat,new(c.agg.cnt*100/g.agg.cnt as percent) as agg)");
    foreach(dynamic r in q2) Console.WriteLine("grp:"+r.grp+"\tcat:"+r.cat+"\tpercent:"+r.agg.percent);
    

    q produces the following SQL query:

    SELECT 
    1 AS [C1], 
    [Project4].[grp] AS [grp], 
    [Project4].[cat] AS [cat], 
    ([Project4].[C1] * 100) / [Project4].[C2] AS [C2]
    FROM ( SELECT 
        [Project3].[cat] AS [cat], 
        [Project3].[grp] AS [grp], 
        [Project3].[C1] AS [C1], 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[A] AS [Extent6]
            WHERE ([Project3].[grp] = [Extent6].[grp]) OR (([Project3].[grp] IS NULL) AND ([Extent6].[grp] IS NULL))) AS [C2]
        FROM ( SELECT 
            [Distinct1].[cat] AS [cat], 
            [Distinct2].[grp] AS [grp], 
            (SELECT 
                COUNT(1) AS [A1]
                FROM  [dbo].[A] AS [Extent4]
                INNER JOIN (SELECT 
          [B].[aid] AS [aid], 
          [B].[cat] AS [cat]
          FROM [dbo].[B] AS [B]) AS [Extent5] ON [Extent4].[id] = [Extent5].[aid]
                WHERE (([Distinct1].[grp] = [Extent4].[grp]) OR (([Distinct1].[grp] IS NULL) AND ([Extent4].[grp] IS NULL))) AND ([Distinct1].[cat] = [Extent5].[cat])) AS [C1]
            FROM   (SELECT DISTINCT 
                [Extent1].[grp] AS [grp], 
                [Extent2].[cat] AS [cat]
                FROM  [dbo].[A] AS [Extent1]
                INNER JOIN (SELECT 
          [B].[aid] AS [aid], 
          [B].[cat] AS [cat]
          FROM [dbo].[B] AS [B]) AS [Extent2] ON [Extent1].[id] = [Extent2].[aid] ) AS [Distinct1]
            INNER JOIN  (SELECT DISTINCT 
                [Extent3].[grp] AS [grp]
                FROM [dbo].[A] AS [Extent3] ) AS [Distinct2] ON ([Distinct1].[grp] = [Distinct2].[grp]) OR (([Distinct1].[grp] IS NULL) AND ([Distinct2].[grp] IS NULL))
        )  AS [Project3]
    )  AS [Project4]
    

    q2 produces shorter SQL query:

    SELECT 
    1 AS [C1], 
    [GroupBy2].[K1] AS [grp], 
    [GroupBy1].[K2] AS [cat], 
    ([GroupBy1].[A1] * 100) / [GroupBy2].[A1] AS [C2]
    FROM   (SELECT 
        [Extent1].[grp] AS [K1], 
        [Extent2].[cat] AS [K2], 
        COUNT(1) AS [A1]
        FROM  [dbo].[A] AS [Extent1]
        INNER JOIN (SELECT 
          [B].[aid] AS [aid], 
          [B].[cat] AS [cat]
          FROM [dbo].[B] AS [B]) AS [Extent2] ON [Extent1].[id] = [Extent2].[aid]
        GROUP BY [Extent1].[grp], [Extent2].[cat] ) AS [GroupBy1]
    INNER JOIN  (SELECT 
        [Extent3].[grp] AS [K1], 
        COUNT(1) AS [A1]
        FROM [dbo].[A] AS [Extent3]
        GROUP BY [Extent3].[grp] ) AS [GroupBy2] ON ([GroupBy1].[K1] = [GroupBy2].[K1]) OR (([GroupBy1].[K1] IS NULL) AND ([GroupBy2].[K1] IS NULL))
    
    0 讨论(0)
提交回复
热议问题