我使用LinqPad 4将linq查询转换为sql。但是我对转换的sql查询非常困惑。我有一个与AppliedJob相关的工作表。 AppliedJob与JobOffer有关。 JobOffer与合同有关。合同表有一个字段CompletedDate,最初在作业合同开始时设置为Null。如果作业完成10,则使用当前日期更新该字段。我想得到那些有CompletedDate的工作清单!= Null(如果在Contract表中找到)。这意味着与合同相关的合同尚未完成或未在合同表中找到。未找到意味着任何合同不是从作业开始的。 我的林克:
from j in Jobs
join jobContract in
(
from appliedJob in AppliedJobs.DefaultIfEmpty()
from offer in appliedJob.JobOffers.DefaultIfEmpty()
from contract in Contracts.DefaultIfEmpty()
select new { appliedJob, offer, contract }
).DefaultIfEmpty()
on j.JobID equals jobContract.appliedJob.JobID into jobContracts
where jobContracts.Any(jobContract => jobContract.contract.CompletedDate != null)
select j.JobTitle
Linqpad做的我的Sql查询:
SELECT [t0].[JobTitle]
FROM [Job] AS [t0]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT NULL AS [EMPTY]
) AS [t1]
LEFT OUTER JOIN ((
SELECT NULL AS [EMPTY]
) AS [t2]
LEFT OUTER JOIN ([AppliedJob] AS [t3]
LEFT OUTER JOIN [JobOffer] AS [t4] ON [t4].[AppliedJobID] = [t3].[AppliedJobID]
LEFT OUTER JOIN [Contract] AS [t5] ON 1=1 ) ON 1=1 ) ON 1=1
WHERE ([t5].[CompletedDate] IS NOT NULL) AND ([t0].[JobID] = [t3].[JobID])
)
我的问题是,为什么它会在查询中生成这么多SELECT NULL AS [EMPTY]
和LEFT OUTER JOIN
?
我能从中做出一个简单易懂的查询吗?或者可以吗?
答案 0 :(得分:3)
DefaultIfEmpty()转换为左外连接。见LEFT OUTER JOIN in LINQ
有很多“NULL为[Empty]”因为NULL!= SQL中的NULL。请参阅为什么NULL = NULL evaluate to false in SQL server
答案 1 :(得分:0)
自从我触及C#和LINQ以来已经有一段时间了,但这是我的看法。
多个左外连接和空值的原因是因为您有几个(延迟?)调用DefaultIfEmpty()
。
没有双关语,但Enumerable.DefaultIfEmpty()
的默认返回值是多少?它是null
。在您开始评估LINQ代码段中的连接条件之前,它们都会被评估和收集。
该代码片段代表方程式的非空右侧。整件事可以归还一套空白。
因此,兼容的SQL语句必须递归地在空集之间创建左外连接,直到实际的SQL连接标准。
这几乎是代数的。尝试了解LINQ和SQL语句都失效了。从头到尾一直向后工作到每个开头,你会看到等价。
答案 2 :(得分:0)
所有SELECT NULL AS [EMPTY]
的原因是这些子查询没有用于返回数据,只是为了验证那里有数据。换句话说,LINQ代码正在优化查询,实际上不会引入任何列数据,因为这些子查询的目的完全没有必要。