我有一个linq查询,如下所示:(一个更大的查询的一部分,但这证明了问题)
from guarantee in tblGuarantees
from nextExptDev in
(from gd in tblGuaranteeDevaluations
where gd.fkGuaranteeId == guarantee.pkGuaranteeId &&
gd.Date == null
orderby gd.ExpectedDate ascending
select new
{
gd.Sum,
gd.CurrencyId,
gd.ExpectedDate
}).Take(1).DefaultIfEmpty()
select new
{
guarantee.pkGuaranteeId,
nextExptDev.Sum,
nextExptDev.CurrencyId,
nextExptDev.ExpectedDate
}
它生成以下SQL:
SELECT [t0].[pkGuaranteeId],
[t3].[Sum] AS [Sum],
[t3].[CurrencyId] AS [CurrencyId],
[t3].[ExpectedDate] AS [ExpectedDate2]
FROM [dbo].[tblGuarantee] AS [t0]
CROSS APPLY ((SELECT NULL AS [EMPTY]) AS [t1]
OUTER APPLY (SELECT TOP (1) [t2].[Sum],
[t2].[CurrencyId],
[t2].[ExpectedDate]
FROM [dbo].[tblGuaranteeDevaluation] AS [t2]
WHERE ( [t2].[fkGuaranteeId] = [t0].[pkGuaranteeId] )
AND ( [t2].[Date] IS NULL )
ORDER BY [t2].[ExpectedDate]) AS [t3])
ORDER BY [t3].[ExpectedDate] -- Why here?
我的问题是,为什么那最后ORDER BY
?在我更大的查询中,它真的会伤害性能而我无法弄清楚为什么需要它。
此外,还有任何关于以更好的方式写这篇文章的提示。
答案 0 :(得分:2)
在查询中,您正在
中执行订单from gd in tblGuaranteeDevaluations
where gd.fkGuaranteeId == guarantee.pkGuaranteeId &&
gd.Date == null
orderby gd.ExpectedDate ascending
这使得内部查询在内部块
中执行顺序SELECT TOP (1) [t2].[Sum], [t2].[CurrencyId], [t2].[ExpectedDate]
FROM [dbo].[tblGuaranteeDevaluation] AS [t2]
WHERE ([t2].[fkGuaranteeId] = [t0].[pkGuaranteeId]) AND ([t2].[Date] IS NULL)
ORDER BY [t2].[ExpectedDate]
但是你正在“加入”2个不同的集合,空集和内部集合,为了确保顺序,代码必须为结果集添加另一个顺序对于“连接”,以便订单在外部集合中的原因是自动代码生成,但由于该集合已经订购,最后的订单不应降低性能。
答案 1 :(得分:1)
如果您使用DefaultIfEmpty()
来电切换Take(1)
会怎样?用FirstOrDefault
电话取代两者怎么样?如何使用let nextExptDev = ...
代替from nextExptDev in ...
?
为我尝试最后一件事......似乎将order by
放在投影中会传达到查询的其余部分,您希望整个事情由此排序。相反,看看您是否可以从订购的来源中选择它。 IE:from gd in tblGuaranteeDevaluations.OrderBy(t => t.ExpectedDate)
。
答案 2 :(得分:-1)
在您的查询中,您正在执行此操作:
orderby gd.ExpectedDate ascending
,这反映在生成的SQL中。