左连接、分组和计数

假设我有这个 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 到 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() }

谢谢!

207868 次浏览
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) }
 (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) })

考虑使用子查询:

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 } ;

迟到的回答:

如果你所做的一切都是 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(而不带 intojoin等价于 Join) :

context.ParentTable
.GroupJoin(
inner: context.ChildTable
outerKeySelector: parent => parent.ParentId,
innerKeySelector: child => child.ParentId,
resultSelector: (parent, children) => new { parent.Id, Count = children.Count() }
);

虽然 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() }

与这里大多数投票的解决方案不同,我们在 计数(t = > t. ChildId! = null)中不需要 J1J2和 null 检查