2016-06-01 30 views
2

我們正在構建一個數據倉庫,我們希望捕獲每個產品的價格並在白天保留這些數據。有一個表FromDateToDate,它們都可以有NULL's。ROW_NUMBER更好的替代方案可以檢索每個組的單個記錄

邏輯找到今天的價格是:

  1. 忽略任何記錄中,其中FromDate是在未來。
  2. 忽略ToDate過去的記錄。
  3. 如果有多條滿足上述條件的記錄,我們希望得到FromDate是最近的價格,而ToDate是最接近當前日期的價格。
  4. 該系統允許重複使用相同的FromDateToDate,所以我們然後按主鍵降序排列(最新的第一個)。

爲了解決這個問題,我使用了ROW_NUMBERPARTITION來訂購記錄,只得到第一個。這是行得通的,但它每天大約需要20分鐘(並且很難達到tempdb),因爲我們有大約200萬條記錄將從此查詢創建。

有沒有更好的選擇可能會增加查詢的性能?

SQL Fiddle here

注意,小提琴是數據的過於簡化的例子,只包含用於此問題相關部分。

+0

你對錶中的任何索引? –

+0

是的,索引不是我的問題。如果有一種方法可以在不使用分析功能的情況下做到這一點,我就會更加流浪。可能會對'tempdb'更友善的東西。這可能是最好的方式,並且由於我擁有大量的數據,我可能不得不忍受它。 – Lock

+1

[** This **](http://dba.stackexchange.com/questions/86415/retrieving-n-rows-per-group)可能會有所幫助。 –

回答

1

這是您的查詢:

SELECT ProductId, @PriceDate AS PriceDate, Price 
FROM (SELECT fp.*, 
      ROW_NUMBER() OVER (PARTITION BY ProductId 
           ORDER BY COALESCE(FromDate, '19000101') DESC, COALESCE(ToDate, '21000101') ASC) AS RowNumber 
     FROM FactPrices fp 
     WHERE (FactPrices.FromDate IS NULL OR FactPrices.FromDate <= @PriceDate) AND 
      (FactPrices.ToDate IS NULL OR FactPrices.ToDate >= @PriceDate) 
    ) A 
WHERE A.RowNumber = 1; 

where子句是一個大的性能殺手。我將建議添加兩個計算列,然後再添加兩個索引。

計算列是:

FromDateNotNull as (coalesce(FromDate, '19000101')) 
ToDateNotNull as (coalesce(ToDate, '21000101')) 

然後,在創建索引:

(Prices, FromDateNotNull desc, ToDateNotNull asc) 
(FromDateNotNull, ToDateNotNull) 

然後,寫一個查詢爲:

SELECT ProductId, @PriceDate AS PriceDate, Price 
FROM (SELECT fp.*, 
      ROW_NUMBER() OVER (PARTITION BY ProductId 
           ORDER BY FromDateNotNull DESC, ToDateNotNull 
          ) AS RowNumber 
     FROM FactPrices fp 
     WHERE FromDateNotNull <= @PriceDate AND 
      ToDateNotNull >= @PriceDate 
    ) A 
WHERE A.RowNumber = 1; 
+0

會試一試!源數據通過SSIS轉儲,因此我可以刪除NULL中的NULL。 – Lock

+0

@Lock。 。 。在where子句中避免使用'或'將允許查詢查詢爲查詢使用索引。 –

+0

我調整了我的查詢來刪除所有的「或」,現在是33秒。謝謝!! – Lock

相關問題