2010-11-10 34 views
0

我有一個歷史記錄表,其中包含每次記錄更改時的快照。我試圖用原始捕獲日期返回某個歷史記錄行。我目前正在使用這個此刻:查找結果的第一行

select 
    s.Description, 
    h.CaptureDate OriginalCaptureDate 
from 
    HistoryStock s 
    left join 
     (select 
       StockId, 
       CaptureDate 
      from 
       HistoryStock 
      where 
       HistoryStockId in (select MIN(HistoryStockId) from HistoryStock group by StockId) 
     ) h on s.StockId = h.StockId 
where 
    s.HistoryStockId = @HistoryStockId 

這工作,但有1萬條記錄其對慢側,我不知道如何優化這個查詢。

此查詢如何優化?

UPDATE

WITH OriginalStock (StockId, HistoryStockId) 
AS (
    SELECT StockId, min(HistoryStockId) 
    from HistoryStock group by StockId 
    ), 
OriginalCaptureDate (StockId, OriginalCaptureDate) 
As (
    SELECT h.StockId, h.CaptureDate 
    from HistoryStock h join OriginalStock o on h.HistoryStockId = o.HistoryStockId 
) 

select 
    s.Description, 
    h.OriginalCaptureDate 
from 
    HistoryStock s left join OriginalCaptureDate h on s.StockId = h.StockId 
where 
    s.HistoryStockId = @HistoryStockId 

我已經更新到使用CTE的代碼,但我沒有更好的性能明智的,只有微小的性能提升。有任何想法嗎?

只是另一個說明,我需要查看StockId的歷史記錄表中的第一條記錄,而不是最早的捕獲日期。

+0

您正在使用HistoryStockId限制最終查詢,我認爲它只限於一個StockId,但看起來您將加入所有歷史記錄以獲得此結果。您是否嘗試過使用參數@HistoryStockId限制CTE?發佈查詢的執行計劃將有所幫助。 – Tony 2010-11-10 13:38:50

+0

您能向我們展示「HistoryStock」所有相關列的列架構嗎? (這裏是唯一的表格,對嗎?) – AakashM 2010-11-10 13:48:35

+0

您似乎有一個額外的CTE,它是多餘的,據我所見,OriginalCaptureDate是不必要的 - 爲什麼不根據它進行最終選擇並選擇您感興趣的字段?。如果INNER JOIN適合,您也正在執行LEFT JOIN。如上所述,您還可以在聲明的最後一點對historystockid進行過濾 - 爲什麼不首先對此進行過濾以減少正在檢查的數據集? – JamWheel 2010-11-16 09:05:58

回答

1

我不確定我完全理解數據如何在您的查詢中工作,但嵌套這樣的查詢在我看來對性能沒有好處。你可以嘗試一下:

WITH MinCaptureDate (StockID, MinCaptureDate) 
AS (
    SELECT HS.StockID 
     ,MIN(HS.CaptureDate) AS OriginalCaptureDate 
    FROM HistoryStock HS 
    GROUP BY 
     HS.Description 
    ) 
SELECT HS.Description 
    ,MCD.OriginalCaptureDate 
FROM HistoryStock HS 
JOIN MinCaptureDate MCD 
    ON HS.StockID = MCD.StockID 
WHERE HS.StockID = @StockID 
+0

感謝您對CTE的建議,但調整我的查詢以使用CTE只會讓我的性能提升2秒。任何其他想法? – adriaanp 2010-11-10 10:47:22

+0

@adriaanp:你說速度提高了2秒,你查詢的執行時間是多少?我一直在使用一些隨機數據進行測試,並且您的查詢在我的服務器上的<1s內返回,使用300萬條記錄...... SQL框的規格是什麼? – Tony 2010-11-10 14:41:19

0

我想我明白你想達到什麼。你基本上要指定歷史記錄股票的說明,但你想用股票第一歷史記錄相關的日期......所以,如果你的歷史表看起來像這樣

StockId HistoryStockId CaptureDate Description 
1   1    Apr 1   Desc 1 
1   2    Apr 2   Desc 2 
1   3    Apr 3   Desc 3 

,並指定@HistoryStockId = 2,你想要的結果如下

Description OriginalCaptureDate 
Desc 2  Apr 1 

我覺得下面的查詢會給你一個稍微好一點的性能。

WITH OriginalStock (StockId, CaptureDate, RowNumber) 
AS ( 
    SELECT 
     StockId, 
     CaptureDate, 
     RowNumber = ROW_NUMBER() OVER (PARTITION BY StockId ORDER BY HistoryStockId ASC) 
    from HistoryStock 
    ) 

select 
    s.Description, 
    h.CaptureDate 
from 
    HistoryStock s left join OriginalStock h on s.StockId = h.StockId and h.RowNumber = 1 
where 
    s.HistoryStockId = @HistoryStockId 
+0

您有語法錯誤,請在WITH子句後面刪除「,」。此外,這個查詢在我的測試中的表現比其他人已經提出的要差很多。 – Tony 2010-11-11 08:25:07