次のようなテーブル スキーマがあります (簡略化)。
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 プロセスと呼びます) からのいくつかの異なるタイプのトランザクションを統合しているため、私は注文をあまり制御できません。挿入されます。私が行ったとしても、トランザクションは遡る可能性があるため、ここで注意すべき重要なことは、特定の最大値が必ずしも最新のトランザクションであるとは限らないということです。TransactionID
customer
実際、最新のトランザクションは日付とID の組み合わせです。日付は一意ではありません。ベンダーは時刻を切り詰めることが多いため、最新のトランザクションを取得するには、まず最新の日付を見つけてから、その日付の最新の ID を見つける必要があります。
ウィンドウ クエリ ( ROW_NUMBER() OVER (PARTITION BY TransactionDate DESC, TransactionID DESC)
) を使用してこれを実行できることはわかっていますが、これには完全なインデックス スキャンと非常にコストのかかる並べ替えが必要なため、効率が大幅に低下します。ずっと書き続けるのもかなり厄介です。
2 つの CTE またはネストされたサブクエリを使用すると、もう少し効率的です。1 つはMAX(TransactionDate)
perを検索しCustomerID
、もう 1 つは を検索しますMAX(TransactionID)
。繰り返しますが、機能しますが、2 番目の集計と結合が必要です。これは、ROW_NUMBER()
クエリよりもわずかに優れていますが、パフォーマンスに関してはかなり苦痛です。
CLR User-Defined Aggregate の使用も検討しており、必要に応じてフォールバックしますが、展開を簡素化するために、可能であれば純粋な SQL ソリューションを見つけたいと思います (これ以外の場所では SQL-CLR は必要ありません)。事業)。
質問は、具体的には次のとおりです。
最新のperを返し、最新 の の最大値として定義されたクエリを作成し、通常の/クエリと同等のパフォーマンスを実現するクエリを作成することは可能ですか?TransactionID
CustomerID
TransactionID
TransactionDate
MAX
GROUP BY
(つまり、計画の重要なステップは、インデックス スキャンとストリーム集計のみにする必要があります。複数のスキャン、並べ替え、結合などは、遅すぎる可能性があります。)