r_h*_*ney 7 sql sql-server common-table-expression
请考虑Sql Server中的以下2个语句:
这个使用嵌套子查询:
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
Run Code Online (Sandbox Code Playgroud)
这使用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
Run Code Online (Sandbox Code Playgroud)
考虑到两个Segments表可能有数百万行,这两个中哪一个可能表现更好?
我的直觉是外部应用会表现得更好.
还有几个问题:
首先,去掉Top 100 PercentCTE 中的 。此处未使用 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
Run Code Online (Sandbox Code Playgroud)
另一种可能
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
Run Code Online (Sandbox Code Playgroud)