使用来自下级组内的顶级组的聚合结果

时间:2011-05-12 16:44:02

标签: database linq grouping aggregate

我有2个表A {int id,int grp},B {int aid,int cat}。

表B包含表A所属记录的类别列表,因此B.aid是引用A.id的外键。

A.id是表A的唯一主键。

B.cat包含1到5的类别编号,A.grp包含1到1000之间的数字。

表A有300万条记录,表B - 约500万条。

对于每个组A.grp我需要计算A组中包含B.cat的记录百分比,其中包含A.grp组中的记录数。

所以如果A:[{1,1},{2,1},{3,2}],B:[{1,3},{1,4},{2,3},{3 ,4}]然后查询结果应该是以下3列表: R {int grp,int cat,double percent}:[{1,3,100},{1,4,50},{2,4,100}]

如何在Linq中使用一个查询执行此操作?

希望A在该查询中只出现一次,因为我希望能够用A.Where(e =>一些复杂的表达式)替换A,而不会在该单个查询中多次复制它。

使用外键将表A和B导入到Linq到实体中,以便可以引用from a in A from b in a.B select b.catfrom b in B select b.A.grp

2 个答案:

答案 0 :(得分:1)

以下是生成所需结果的SQL代码:

with grp as (select a.grp,cnt=count(*) from a group by a.grp)
,cat as(select a.grp,b.cat,cnt=count( * ) * 100/grp.cnt
from a
join b on b.aid=a.id
join grp on grp.grp=a.grp
group by a.grp,b.cat,grp.cnt)
select * from cat

以下是产生所需结果的Linq代码:

var grp=
        from a in db.A
        group a by new{grp=a.grp}
        ;

var cat=
        from a in db.A
        from b in a.B
        group b by new{a.grp,b.cat}
        ;

var q=from g in grp
        join c in cat on g.Key.grp equals c.Key.grp
        select new{g.Key.grp,c.Key.cat,percent=c.Count()*100/g.Count()};

但是有这样的事情会很好:

from a in db.A
group a by new{grp=a.grp} into grp
from g in grp
from c in g.B
group c by new{gcnt=grp.Count(),c.cat} into cat
from c in cat
select new{c.A.grp,c.cat,cnt=cat.Count()*100/cat.Key.gcnt}

但是它给了我以下运行时异常: 不支持嵌套查询。 Operation1 ='GroupBy'Operation2 ='MultiStreamNest'“

答案 1 :(得分:1)

您可以像这样组合查询

var query = from g in 
              (from a in db.A
               group a by new
               {
                 grp = a.grp
               }
              )
            join c in  
              (from a in db.A
               from b in a.B
               group b by new
               {
                 a.grp,
                 b.cat
               }
              )            
            on g.Key.grp equals c.Key.grp
            select new
            {
              g.Key.grp,
              c.Key.cat,
              percent = c.Count() * 100 / g.Count()
            };