2011-03-09 55 views
4

基本上我正在做一个报告类型查询,我从多个表中汇总数据并将它连接到单个表。Linq to SQL:左加入分组集合使交叉应用/外部应用

它看起来有点像这样:

var docs = from x in DB.Docs 
      group x by x.PersonId into g 
      select new { 
       g.Key, 
       totalSent = g.Sum(x => x.SentDate.HasValue ? 1 : 0), 
       lastSent = g.Max(x => x.SentDate) 
       ... 
      }; 

var summary = from x in DB.People 
       from y in docs.Where(y => y.Key == x.Id).DefaultIfEmpty() 
       select new { 
        x.Id, 
        x.Name, 
        y.totalSent, 
        y.lastSent 
       } 

我希望,这创造了左加入DB.Peopledocs的结果,而是我得到一些疯狂的东西CROSS APPLY((SELECT NULL AS [EMPTY]) as [t1] OUTER APPLY ... SQL。

我试过左连接语法的每个变体,我可以想到,我甚至在另一个查询中包装了docs,并且我得到了同样的结果。

我缺少什么?

+0

你没有得到你想要的结果? 'CROSS APPLY'可能看起来很疯狂,但就我的经验而言,LINQ to SQL通常比我用SQL更聪明,我只是让它做它的事情......如果结果是正确的。 – shaunmartin 2011-03-09 19:41:47

+1

结果永远不会回来......'OUTER APPLY'基本上使得我的分组集合成为'DB.People'每行的表值函数。查询超时。 – 2011-03-09 20:43:33

回答

0
from x in DB.People 
from y in docs.Where(y => y.Key == x.Id).DefaultIfEmpty() 

以上将清楚地产生笛卡尔结果,后来被过滤。

也许你的意思是加入:

from x in DB.People 
join y2 in docs on x.Id equals y2.Key into g 
from y in g.DefaultIfEmpty() 

如何:

from x in DB.People 
let g = x.Docs 
select new 
{ 
    x.Id, 
    x.Name, 
    totalSent = g.Sum(y => y.SentDate.HasValue ? 1 : 0), 
    lastSent = g.Max(y => y.SentDate) 
} 
+0

我的版本是一个快捷方式,如果'docs'不代表分组集合,它会创建一个左连接。 – 2011-03-09 22:26:43

+0

所以你用我的方法得到相同的SQL? – 2011-03-09 23:27:10

+0

是的,这两种方法让你相同的SQL。第二个例子不能工作,因为这些POCO对象是建立在具有直接L2S映射的有些笨重的数据库架构之上的,所以我没有时间去改变。例如,Docs对3个表格表示相当有趣的查询。 – 2011-03-09 23:48:32