3

我有一个如下所示的 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?在我更大的查询中,这确实会损害性能,我无法弄清楚为什么需要它。

此外,任何关于以更好的方式编写此内容的提示都值得赞赏。

4

3 回答 3

2

在查询中,您正在执行 order by

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 个不同的集合,即空集和内部块集,为此,为了确保顺序,代码必须为“加入”的结果集设置另一个order by,所以为什么order 在外部集合中,是自动代码生成,但是由于集合已经排序,最后一个order by不应该降低性能。

于 2013-02-06T12:43:22.720 回答
1

如果你DefaultIfEmpty()Take(1)通话切换会发生什么?用一个FirstOrDefault电话代替两者怎么样?只使用let nextExptDev = ...而不是from nextExptDev in ...呢?

为我尝试最后一件事......似乎将 放在order by投影中是向查询的其余部分传达您希望整个事物按此排序。相反,看看您是否可以从订购的源中选择它。即:from gd in tblGuaranteeDevaluations.OrderBy(t => t.ExpectedDate)

于 2013-02-07T20:32:16.550 回答
-1

in your query you're doing this:

orderby gd.ExpectedDate ascending and that is reflected in the SQL generated.

于 2013-02-07T21:05:17.107 回答