【问题标题】:LINQ exclusionLINQ 排除
【发布时间】:2009-02-03 15:10:12
【问题描述】:

是否有直接的 LINQ 语法来查找集合 B 中不存在的集合 A 的成员?在 SQL 中我会写这个

SELECT A.* FROM A LEFT JOIN B ON A.ID = B.ID WHERE B.ID IS NULL

【问题讨论】:

  • 你的意思是左外连接,我猜?
  • 是的。 OUTER 是纯语法糖,是可选的 (qv SQL-92)。
  • 对。我只是习惯了 Oracle (+) 语法。

标签: sql linq


【解决方案1】:

请参阅Except operator 上的 MSDN 文档。

【讨论】:

  • 这是我第一次得到完整、直接适用和有效的答案。
【解决方案2】:
var results = from itemA in A
              where !B.Any(itemB => itemB.Id == itemA.Id)
              select itemA;

【讨论】:

  • 这个查询在 7.5 秒内针对 2 个大表运行并生成了一个不错的 where not exists 查询。
  • ItemB 在哪里实例化?
【解决方案3】:

我相信您的 LINQ 将类似于以下内容。

var items = A.Except(
  from itemA in A
  from itemB in B
  where itemA.ID == itemB.ID
  select itemA);

更新

如 cmets 中的 Maslow 所示,这可能不是性能最高的查询。与任何代码一样,执行某种级别的分析以消除瓶颈和低效算法非常重要。在这种情况下,chaowman's answer 提供了更好的执行结果。

稍微检查一下查询就可以看出原因。在我提供的示例中,A 集合上至少有两个循环 - 1 用于组合 A 和 B 列表,另一个用于执行 Except 操作 - 而在 chaowman's answer 中(转载如下),A 集合只迭代一次。

// chaowman's solution only iterates A once and partially iterates B
var results = from itemA in A
              where !B.Any(itemB => itemB.Id == itemA.Id)
              select itemA;

另外,在我的回答中,B 集合针对 A 中的每个项目进行了整体迭代,而在 chaowman's answer 中,它仅迭代到找到匹配项的点。

如您所见,即使在查看生成的 SQL 之前,您也可以仅从查询本身发现潜在的性能问题。再次感谢 Maslow 强调这一点。

【讨论】:

  • 这个 LINQ 在 LINQPad 中生成了一个非常糟糕的 SQL 查询,需要 1 分 17 秒才能针对 2 个非常大的表运行。 chaowman 耗时 7.5 秒。在大规模实施之前,我会检查每个答案的效率。
  • @Maslow:你说得对,毫无疑问,查询需要像任何其他代码一样进行分析和优化,但首先让它工作然后优化很重要。在你真正分析这些之前,你真的知道哪一个会表现得更好。
  • 是的,这当然可能是这个遗留数据库中缺少键。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 2012-09-25
相关资源
最近更新 更多