【问题标题】:How to write a LEFT OUTER JOIN where the right side is null in LINQ to SQL?如何在 LINQ to SQL 中编写右侧为空的 LEFT OUTER JOIN?
【发布时间】:2021-03-01 16:15:19
【问题描述】:

如何在 LINQ to SQL 中编写 LEFT OUTER JOIN,其中右侧为空?

我想要的结果的图形表示是这样的:

图片来源Jeff Atwood

以这条 SQL 为例:

select Document.*
from Document left outer join Invoice
     on Document.DocumentId = Invoice.DocumentId
where Invoice.DocumentId is null

基本上我想要所有不是发票而是其他类型的文件的文件,没关系。

我将非常感谢 LINQ 查询语法和 LINQ 方法(流利)语法中的示例。

谢谢!

【问题讨论】:

标签: c# linq linq-to-sql


【解决方案1】:

首先,即使在 SQL 中,查询确实应该是 not exists,但通常是 more efficient than the left join / is null construct

编译器也更好地理解exists,因为它理解not exists 不能向结果集中添加更多行,因此它可以保留任何可能存在的唯一性保证。编译器没有看到带有is null 检查的left join 不能添加行(也许应该,但目前没有内置的逻辑可以这样做)。

select Document.*
from Document
where not exists (select 1
    from Invoice
    where Document.DocumentId = Invoice.DocumentId);

现在很明显如何在 Linq 中做到这一点:

var docs =
    from doc in Documents
    where !Invoices.Any(inv => doc.DocumentId == inv.DocumentId);

var docs =
    Documents
    .Where(doc => !Invoices.Any(inv => doc.DocumentId == inv.DocumentId));

【讨论】:

  • 伟大的查理!谢谢。
  • @charlieface 我建议阅读更多关于 TSQL 中的 LEFT OUTER JOIN 的信息 - subquery-or-leftouter-join-performance-wise。虽然您的回答有效,但我不相信您关于 LEFT JOIN 效率较低的说法是正确的。
  • @RyanWilson 您可以从阅读 this article by Aaron Bertrand 开始。我还将告诉您,当编译器可以保证特定连接不会向先前的结果添加更多行时,它通常会获得优势。它只能对半连接或反连接执行此操作,而不是左连接/为空构造。我同意你的观点,编译器应该有这样的逻辑,但今天它不存在。我把那个帖子读到了最后,但看不到任何内容可以改变我的想法。
  • @RyanWilson 已经进一步澄清了
  • 确实,这是常规左连接的方法,Stack Overflow 上已经有一百个这样的帖子。但是您的问题并没有这么说,您的问题是“如何在 LINQ to SQL 中编写 LEFT OUTER JOIN,其中右侧为空?”答案是将其重写为not exists
猜你喜欢
  • 1970-01-01
  • 2021-06-11
  • 2010-12-13
  • 1970-01-01
  • 2014-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
相关资源
最近更新 更多