Linq2SQL生成的奇怪SQL

时间:2013-02-06 12:21:04

标签: c# sql linq linq-to-sql

我有一个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?在我更大的查询中,它真的会伤害性能而我无法弄清楚为什么需要它。

此外,还有任何关于以更好的方式写这篇文章的提示。

3 个答案:

答案 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中。