如何在 LINQ to SQL 中编写右侧为空的 LEFT OUTER JOIN?
Posted
技术标签:
【中文标题】如何在 LINQ to SQL 中编写右侧为空的 LEFT OUTER JOIN?【英文标题】:How to write a LEFT OUTER JOIN where the right side is null in LINQ to SQL? 【发布时间】: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 方法(流利)语法中的示例。
谢谢!
【问题讨论】:
也许这会有所帮助:linq-to-sql-left-outer-join @RyanWilson 不过,这并不是真正的左连接 【参考方案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
以上是关于如何在 LINQ to SQL 中编写右侧为空的 LEFT OUTER JOIN?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Linq 的 where 条件下从可为空的日期时间中删除时间部分