2011-05-11 76 views
3

我有一大堆的記錄表中​​的變量,像這樣:幫助避免遊標列計算

Id  ProductId Rank RankCreated 
1  123213  2  2011-05-02 
2  123213  4  2011-05-03 
3  123213  1  2011-05-03 
4  155432  10  2011-05-01 
5  155432  10  2011-05-02 

編號是標識列我加入到我的表變量(將解釋爲什麼我需要它一會兒)。 產品編號產品排名是表示產品在給定時間的排名的值。 RankCreated產品排名的時間。

什麼我嘗試做:

計算每個產品級別之間的「運動」,每個產品。其中「運動」被定義爲當前 - 前一個。

所以「計算列」應該是這樣的:

Id  ProductId Rank RankCreated Movement 
1  123213  2  2011-05-02 NULL 
2  123213  4  2011-05-03 2 
3  123213  1  2011-05-03 -3 
4  155432  10  2011-05-01 NULL 
5  155432  10  2011-05-02 0 

我加入了標識列,所以我可以用它來獲取此前的紀錄。

這裏就是我得到的數據到臨時表:

insert into @rankhistories (productid, [rank], [rankcreated]) 
select a.ProductId, b.[rank] 
from dbo.ProductRankHistories b 
inner join dbo.Products a on a.ProductId = b.ProductId 
order by a.ProductId, b.RankCreated 

我實在看不出我怎麼能避免此光標。該表變量中有6000多條記錄,而我的光標解決方案需要5秒鐘,這是不可接受的。

任何人都可以幫忙嗎?

回答

4
DECLARE @TV TABLE 
(
Id INT IDENTITY(1,1) PRIMARY KEY, 
ProductId INT, 
Rank INT, 
RankCreated DATE 
) 


/*Populate *6000 rows of random data*/ 
INSERT INTO @TV 
SELECT TOP 6000 
       ROW_NUMBER() OVER (ORDER BY (SELECT 0))/9 AS ProductId, 
       CRYPT_GEN_RANDOM(1) % 10 AS Rank, 
       GETDATE() AS RankCreated 
FROM master..spt_values v1,master..spt_values v2 


SELECT t1.Id, 
     t1.ProductId, 
     t1.Rank, 
     t1.RankCreated, 
     t2.Rank - t1.Rank AS Movement 
FROM @TV t1 
LEFT MERGE JOIN @TV t2 ON t1.Id = t2.Id+1 AND t1.ProductId=t2.ProductId 
ORDER BY t1.Id 
+0

聰明 - 但實際上需要比光標更長的時間 - 需要6秒鐘。執行計劃顯示SORT花費了63%的成本。 – RPM1984 2011-05-11 23:59:04

+0

@ rpm1984 - 您是否將'Id'列設置爲主鍵,因此它具有索引? (我猜不是因爲我看不到排序)Join在執行計劃中看起來像什麼?實際上你可能會在這裏使用'#temp'表獲得比'@tablevariable'更好的性能。 – 2011-05-12 00:01:58

+0

@Martin - 加PK沒有效果。 SORT從執行計劃中刪除,但仍然是5秒。但是使用#temp表格,它現在是即時的! 0秒!你搖滾 - 謝謝! +1並且接受 – RPM1984 2011-05-12 00:20:36