views:

11942

answers:

4

Let's say I have this SQL:

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

How can I translate this into LINQ to SQL? I got stuck at the COUNT(c.ChildId), the generated SQL always seems to output COUNT(*). Here's what I got so far:

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

Thank you!

+24  A: 
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) }
Mehrdad Afshari
OK, that works, but why? How do you think through it? How does not counting null values give us the same as COUNT(c.ChildId)? Thanks.
pbz
This is how SQL works. COUNT(fieldname) will count the rows in that field that are not null. Maybe I don't get your question, please clarify if that's the case.
Mehrdad Afshari
I guess I always thought about it in terms of counting rows, but you are correct, only the non-null values are counted. Thanks.
pbz
.Count() will generate COUNT(*) which will count all the rows in that group, by the way.
Mehrdad Afshari
I've been trying to get this work for hours, thank you soo much! :-)
Ian Devlin
+3  A: 
 (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) })
A: 

Hey... Thanks a lot...it saved my time too..... If we specifically want count of rows of table, then we can play around in the count clause...since we have the key of Parent table.....

+1  A: 

Why join when you can subquery?

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 } ;
David B
If I remember correctly (it's been a while), that query was a simplified version of a large one. If all I needed was the key and count your solution would've been cleaner / better.
pbz
Your comment doesn't make sense in context with original question and upvoted answers. Additionally - if you want more than the key, you have the whole parent row to draw from.
David B