LINQ - 左连接,分组依据和计数

时间:2009-03-29 22:26:00

标签: c# .net linq linq-to-sql

假设我有这个SQL:

SELECT p.ParentId, COUNT(c.ChildId)
FROM ParentTable p
  LEFT OUTER JOIN ChildTable c ON p.ParentId = c.ChildParentId
GROUP BY p.ParentId

如何将其转换为LINQ to SQL?我被困在COUNT(c.ChildId),生成的SQL似乎总是输出COUNT(*)。这是我到目前为止所得到的:

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1
from j2 in j1.DefaultIfEmpty()
group j2 by p.ParentId into grouped
select new { ParentId = grouped.Key, Count = grouped.Count() }

谢谢!

5 个答案:

答案 0 :(得分:183)

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1
from j2 in j1.DefaultIfEmpty()
group j2 by p.ParentId into grouped
select new { ParentId = grouped.Key, Count = grouped.Count(t=>t.ChildId != null) }

答案 1 :(得分:55)

考虑使用子查询:

from p in context.ParentTable 
let cCount =
(
  from c in context.ChildTable
  where p.ParentId == c.ChildParentId
  select c
).Count()
select new { ParentId = p.Key, Count = cCount } ;

如果查询类型通过关联连接,则简化为:

from p in context.ParentTable 
let cCount = p.Children.Count()
select new { ParentId = p.Key, Count = cCount } ;

答案 2 :(得分:32)

迟到的答案:

如果您所做的只是Count(),那么根本不需要左连接。请注意,join...into实际上已转换为GroupJoin,这会返回new{parent,IEnumerable<child>}等分组,因此您只需要在该群组上调用Count()

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into g
select new { ParentId = p.Id, Count = g.Count() }

在扩展方法语法中,join into相当于GroupJoin(而没有join的{​​{1}}为into):

Join

答案 3 :(得分:7)

 (from p in context.ParentTable     
  join c in context.ChildTable 
    on p.ParentId equals c.ChildParentId into j1 
  from j2 in j1.DefaultIfEmpty() 
     select new { 
          ParentId = p.ParentId,
         ChildId = j2==null? 0 : 1 
      })
   .GroupBy(o=>o.ParentId) 
   .Select(o=>new { ParentId = o.key, Count = o.Sum(p=>p.ChildId) })

答案 4 :(得分:7)

虽然LINQ语法背后的想法是模拟SQL语法,但您不应该总是想到将SQL代码直接转换为LINQ。在这种特殊情况下,我们不需要分组,因为加入是一个群组加入。

这是我的解决方案:

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into joined
select new { ParentId = p.ParentId, Count = joined.Count() }

与此处的大多数投票解决方案不同,我们不需要 j1 j2 并在计数(t =&gt; t.ChildId)中进行空检查!= null)