我有類似以下內容(簡化)表模式:如何有效計算一列中的MAX,並按另一列排序?
CREATE TABLE Transactions
(
TransactionID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
CustomerID int NOT NULL, -- Foreign key, not shown
TransactionDate datetime NOT NULL,
...
)
CREATE INDEX IX_Transactions_Customer_Date
ON Transactions (CustomerID, TransactionDate)
給這裏有點背景的,這個事務表實際上是從另一個供應商的數據庫整合幾種不同類型的交易(我們會打電話給它是一個ETL過程),因此我不能很好地控制它們插入的順序。即使我這樣做了,交易也可能會回來,所以這裏需要注意的是對於任何給定的customer
的最大TransactionID
不一定是最近的交易。
事實上,最近的交易是日期和 ID的組合。日期不是唯一的 - 供應商通常會截斷一天中的時間 - 爲了獲得最近的交易,我必須先找到最近的日期,然後找到該日期的最新ID。
我知道我可以用窗口查詢(ROW_NUMBER() OVER (PARTITION BY TransactionDate DESC, TransactionID DESC)
)來做到這一點,但這需要完整的索引掃描和非常昂貴的排序,因此在效率方面失敗了。不停地寫作也很尷尬。
稍微更有效的是使用兩個CTE或嵌套子查詢,一個找到MAX(TransactionDate)
每CustomerID
,另一個找到MAX(TransactionID)
。同樣,它可以工作,但需要第二次聚合和加入,這比ROW_NUMBER()
查詢稍好,但仍然相當痛苦的性能明智。
我也考慮過使用CLR用戶定義的聚合,如果有必要的話,將回退,但我更希望找到一個純粹的SQL解決方案,如果可能的話,以簡化部署(不需要SQL-CLR這個項目的其他地方)。
所以現在的問題,具體爲:
是否可以編寫一個查詢將返回最新TransactionID
每CustomerID
,定義爲最大TransactionID
對於最近TransactionDate
,並實現了計劃相當於在性能上向普通MAX
/GROUP BY
查詢?
(換句話說,在該計劃的唯一顯著的步驟應該是一個索引掃描和數據流聚集。多重掃描,排序,連接等可能是太慢了。)
即使這對實現細節有一點點亮,結合字段的*概念實際上是需要的想出一個優化的解決方案我討厭自我接受,我會給你支票。 ;) – Aaronaught 2010-07-09 14:10:29