LINQ - Left Join, Group By и Count
Скажем, у меня этот 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() }
Спасибо!
Ответы
Ответ 1
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) }
Ответ 2
Рассмотрим использование подзапроса:
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 } ;
Ответ 3
ПОСЛЕДНИЙ ОТВЕТ:
Вам не нужно левое соединение вообще, если все, что вы делаете, это 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() }
В синтаксисе метода расширения a join into
эквивалентно GroupJoin
(while a join
без into
есть join
):
context.ParentTable
.GroupJoin(
inner: context.ChildTable
outerKeySelector: parent => parent.ParentId,
innerKeySelector: child => child.ParentId,
resultSelector: (parent, children) => new { parent.Id, Count = children.Count() }
);
Ответ 4
(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) })
Ответ 5
Хотя идея синтаксиса LINQ состоит в том, чтобы эмулировать синтаксис SQL, вы не должны всегда думать о прямом переводе кода SQL в LINQ. В этом конкретном случае нам не нужно делать группу в, так как join в - это объединение группы.
Здесь мое решение:
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 и нулевая проверка в Count (t = > t.ChildId!= null )