web-dev-qa-db-ja.com

LINQ-左結合、グループ化、およびカウント

私はこの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() }

ありがとうございました!

164
pbz
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) }
183
Mehrdad Afshari

サブクエリの使用を検討してください。

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 } ;
55
Amy B

後の回答:

(左結合は必要ありません 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 intoGroupJoinと同等です(joinのないintoJoinです):

context.ParentTable
    .GroupJoin(
                   inner: context.ChildTable
        outerKeySelector: parent => parent.ParentId,
        innerKeySelector: child => child.ParentId,
          resultSelector: (parent, children) => new { parent.Id, Count = children.Count() }
    );
33
Eren Ersönmez
 (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) })
7
雪域飞貂

LINQ構文の背後にある考え方はSQL構文をエミュレートすることですが、SQLコードを直接LINQに変換することを常に考えるべきではありません。この特定のケースでは、join intoはグループ結合そのものなので、group intoを行う必要はありません。

私のソリューションは次のとおりです。

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

ここでほとんど投票されたソリューションとは異なり、j1j2およびnullチェックインは必要ありませんCount(t => t.ChildId!= null)

7
Mosh