我需要在条件为ORs而不是ANDs的多个条件下进行左连接.我已经找到了很多后者的样本,但我正在努力为我的场景找到正确的答案.
from a in tablea
join b in tableb on new { a.col1, a.col2 } equals new { b.col1, b.col2 }
group a by a into g
select new () { col1 = a.col1, col2 = a.col2, count = g.Count() }
Run Code Online (Sandbox Code Playgroud)
适用于所有条件必须匹配的连接.我需要让联接匹配on a.col1 = b.col1 OR a.col2 = b.col2.
我知道这一定很容易,但我在这个问题上一片空白!
编辑:
为了提供更多信息,查询的目的是获得包含"a"中所有字段的投影以及"b"中匹配记录的计数.我修改了上面的示例,试图说明我追求的是什么.当我使用上述方法运行时,Jon Skeet已经注意到我从a获得了所有记录的计数,而不是b中相关记录的计数.
基本左连接工作正常:
from a in tablea
from b in tableb
.Where( b => ( a.col1 == b.col1 || a.col2 == b.col2))
.DefaultIfEmpty()
select new { col1 = a.col1, col2 = a.col2 }
Run Code Online (Sandbox Code Playgroud)
如果我修改它以添加如下分组
from a in tablea
from b in tableb
.Where( b => ( a.col1 == b.col1 || a.col2 == b.col2))
.DefaultIfEmpty()
group a by a.col1 into g
select new { col1 = g.Key, count = g.Count() }
Run Code Online (Sandbox Code Playgroud)
我得到了从a返回的记录的计数 - 而不是b中匹配的记录数.
编辑:
我会给Jon一个答案 - 我已经解决了我的计数问题 - 我没有意识到我可以使用lamda来过滤计数(g.Count(x => x != null)).另外,我需要按照上面的方式将b分组,而不是按照上面的方式分组.这给出了正确的结果,但SQL不像我手工编写的那样有效,因为它添加了一个相关的子查询 - 如果有人可以建议更好的方式来编写它来模拟以下SQL我会很感激!
select a.col1, count(b.col1)
from tablea a
left join tableb b
on a.col1 = b.col1
or a.col2 = b.col2
group by a.col1
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 36
LINQ只直接支持equijoins.如果您想进行任何其他类型的连接,您基本上需要交叉连接并且where:
from a in tablea
from b in tableb
where a.col1 == b.col1 || a.col2 == b.col2
select ...
Run Code Online (Sandbox Code Playgroud)
可能值得检查生成的SQL是什么样的以及查询计划是什么样的.可能有更有效的方法,但这可能是最简单的方法.
Eam*_*nne 21
根据查询提供程序,您可以选择使用两个from子句:
from a in tablea
from b in tableb
where a.col1 == b.col1 || a.col2 == b.col2
Run Code Online (Sandbox Code Playgroud)
如果您在数据库上执行,那将同样有效.如果您执行内存(Linq to Objects),这将枚举所有可能的组合,这可能是低效的.
Arg,Skeeted ;-).
更高效的Linq to Objects替代品是可能的.该join运营商列举每个源只有一次,然后就一个散列连接,所以你可能分裂或从句分成两个单独的连接,然后把他们的工会.linq中的联合只是一个没有重复的连接,所以看起来如下:
(from a in tablea
join b in tableb on a.Col1 equals b.Col1
select new {a, b})
.Concat(
from a in tablea
join b in tableb on a.Col2 equals b.Col2
select new {a, b}
).Distinct()
Run Code Online (Sandbox Code Playgroud)
这种方法很有效,而且它只是一个查询,但从某种意义上说,代码的性能特征依赖于详细了解linq的工作原理,这有点不明显.就个人而言,如果你想进行可能多次匹配的散列连接,一个更明显的工具就是ToLookup.使用它的替代方案可能如下所示:
var bBy1 = tableb.ToLookup(b=>b.Col1);
var bBy2 = tableb.ToLookup(b=>b.Col2);
var q3 =
from a in tablea
from b in bBy1[a.Col1].Concat(bBy2[a.Col2]).Distinct()
...
Run Code Online (Sandbox Code Playgroud)
这个解决方案实际上更短,它工作的原因更明显,所以这是我更喜欢的.请记住,如果将||操作符拆分为两个单独的查询,如上述两种情况,则需要手动避免重复计算结果(即使用Distinct).
| 归档时间: |
|
| 查看次数: |
32987 次 |
| 最近记录: |