Подсчет процентов строк с категорией от общего числа строк с использованием Dynamic Linq - PullRequest

1 Ответ

1 голос
/ 18 мая 2011

Желаемый результат в q и q2.
q показывает комбинацию агрегатов с разных уровней группировки в одном выражении.
q2 использует вычисленную агг из предыдущих уровней и генерирует более короткий запрос SQL.

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 создает следующий SQL-запрос:

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 создает более короткий запрос SQL:

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))
...