请在Sql Server中考虑以下两个语句:
这个使用嵌套子查询:
WITH cte AS
(
SELECT TOP 100 PERCENT *
FROM Segments
ORDER BY InvoiceDetailID, SegmentID
)
SELECT *, ReturnDate =
(SELECT TOP 1 cte.DepartureInfo
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID),
DepartureCityCode =
(SELECT TOP 1 cte.DepartureCityCode
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID)
FROM Segments seg
这使用OUTER APPLY运算符:
WITH cte AS
(
SELECT TOP 100 PERCENT *
FROM Segments
ORDER BY InvoiceDetailID, SegmentID
)
SELECT seg.*, t.DepartureInfo AS ReturnDate, t.DepartureCityCode
FROM Segments seg OUTER APPLY (
SELECT TOP 1 cte.DepartureInfo, cte.DepartureCityCode
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID
) t
考虑到两个Segments表可能有数百万行,这两个中哪一个可能会表现得更好?
我的直觉是外部应用会表现得更好。
还有几个问题:
答案 0 :(得分:4)
首先,摆脱CTE中的Top 100 Percent
。你没有在这里使用TOP,如果你想对结果进行排序,你应该在整个语句的末尾添加一个Order By。其次,为了解决你关于性能的问题,如果被迫做出猜测,我的赌注只会在第二种形式,因为它只有一个子查询而不是两个子查询。第三,你可能尝试的另一种形式是:
With RankedSegments As
(
Select S1.SegmentId, ...
, Row_Number() Over( Partition By S1.SegmentId Order By S2.SegmentId ) As Num
From Segments As S1
Left Join Segments As S2
On S2.InvoiceDetailId = S1.InvoiceDetailId
And S2.SegmentId > S1.SegmentID
)
Select ...
From RankedSegments
Where Num = 1
另一种可能性
With MinSegments As
(
Select S1.SegmentId, Min(S2.SegmentId) As MinSegmentId
From Segments As S1
Join Segments As S2
On S2.InvoiceDetailId = S1.InvoiceDetailId
And S2.SegmentId > S1.SegmentID
Group By S1.SegmentId
)
Select ...
From Segments As S1
Left Join (MinSegments As MS1
Join Segments As S2
On S2.SegmentId = MS1.MinSegmentId)
On MS1.SegmentId = S1.SegmentId
答案 1 :(得分:1)
也许我会使用托马斯查询的这种变体:
WITH cte AS
(
SELECT *, Row_Number() Over( Partition By SegmentId Order By InvoiceDetailID, SegmentId ) As Num
FROM Segments)
SELECT seg.*, t.DepartureInfo AS ReturnDate, t.DepartureCityCode
FROM Segments seg LEFT JOIN cte t ON seg.InvoiceDetailID = t.InvoiceDetailID AND t.SegmentID > seg.SegmentID AND t.Num = 1