Linq中不等谓词的外连接等价

Posted

技术标签:

【中文标题】Linq中不等谓词的外连接等价【英文标题】:Equivalent of outer join with non-equals predicate in Linq 【发布时间】:2015-09-24 15:03:54 【问题描述】:

我正在寻找以下 SQL 的 Linq 等效项:

SELECT t0.Fk_CompanyId, t0.CheckedUtc, t0.IsBlocking
  FROM MyTable t0
  LEFT OUTER JOIN MyTable t1
    ON t0.Fk_CompanyId = t1.Fk_CompanyId AND t0.CheckedUtc < t1.CheckedUtc
 WHERE t1.Fk_CompanyId IS NULL
   AND t0.CheckedUtc IS NOT NULL

我与 Linq 最接近的是:

from t0 in MyTable
join t1 in MyTable on t0.Fk_CompanyId equals t1.Fk_CompanyId into t1tmp
from t1 in t1tmp.DefaultIfEmpty()
where t1.Fk_CompanyId == null && t0.CheckedUtc != null && t0.CheckedUtc < t1.CheckedUtc
select new  cid = t0.Fk_CompanyId, cuct = t0.CheckedUtc, isbl = t0.IsBlocking 

... 生成以下 SQL(稍微重新格式化):

SELECT t0.Fk_CompanyId, t0.CheckedUtc, t0.IsBlocking
  FROM MyTable AS t0
  LEFT OUTER JOIN MyTable AS t1
    ON t0.Fk_CompanyId = t1.Fk_CompanyId
 WHERE (t1.Fk_CompanyId IS NULL)
   AND (t0.CheckedUtc IS NOT NULL)
   AND (t0.CheckedUtc < t1.CheckedUtc)

这些并不完全等价。 (t0.CheckedUtc &lt; t1.CheckedUtc 被推送到WHERE。)当我在t0.CheckedUtc &lt; t1.CheckedUtc 上进行左外连接时,这会在连接的右侧产生 NULL 值。当我使用 WHERE 过滤时,这会删除我感兴趣的所有 NULL 值。

透视:我正在尝试在 MyTable 中查找具有最新 CheckedUtc 的行,如果有任何非 NULL 行,按 Fk_CompanyId。我希望每个 Fk_CompanyId 有一行。有几个“可能的重复项”只处理查找最近的 CheckedUtcs(而不是它们各自的行),或者假设 CheckedUtc 不是 NULL。

那么:如何在 Linq 中对不等于谓词执行等价的连接?

【问题讨论】:

【参考方案1】:

试试这个

from t0 in MyTable
From t1 in MyTable( x=>x.Fk_CompanyId=t0.Fk_CompanyId && x.CheckedUtc > t0.CheckedUtc ).DefaultIfEmpty()
where t1.Fk_CompanyId == null && t0.CheckedUtc != null 
select new  cid = t0.Fk_CompanyId, cuct = t0.CheckedUtc, isbl = t0.IsBlocking 

【讨论】:

谢谢你,@MukeshKalgude!!!所以诀窍是将连接条件放在被连接表的.Where() 子句中。 我听不懂你在说什么 对不起,没关系。 LINQPad 在捉弄我。我会删除我的评论。

以上是关于Linq中不等谓词的外连接等价的主要内容,如果未能解决你的问题,请参考以下文章

LINQtoSQL 生成的 SQL 中的外连接过多

使用不匹配的外键连接两个表时的空结果集

深入理解关系中的外连接,左外连接,右外连接

如何在 2 个谓词上对 2 个表进行 LINQ 左连接?

在 Redshift 更新查询中使用左外连接导致错误:目标表必须是等连接谓词的一部分

sql条件下解码中的外连接