web-dev-qa-db-ja.com

集計行のIDを取得

最新の日付に対応する値を取得する次のクエリがあります。

SELECT MAX(RowAddedDate), X, Y
FROM dbo.MyTable
GROUP BY X, Y

これで問題ありませんが、このクエリの各行のIDを取得する必要があります。ただし、IDを追加すると、IDがGROUP BY

どうすればこれを解決できますか?

5
BanksySan

ウィンドウ(ランキング)を使用できます。このための関数:

_WITH ct AS
  ( SELECT X, Y, RowAddedDate, ID,
           Rn = DENSE_RANK() OVER (PARTITION BY X, Y
                                   ORDER BY RowAddedDate DESC)
    FROM dbo.MyTable
  )
sELECT X, Y, RowAddedDate, ID
FROM ct 
WHERE Rn = 1 ;
_

複数の行が同じ日付と同じXとYを持っている場合、DENSE_RANK()により、すべての行が返されます。

1つだけ必要な場合は、それをROW_NUMBER()で置き換え、_ORDER BY_を調整して、どの結合行が返されるかを制御できます。

効率に関しては、_(X, Y, RowAddedDate) INCLUDE (ID)_のインデックスが役立ちます。

10
ypercubeᵀᴹ

ウィンドウMAX()を使用して、意味的に非常に近い方法で結果を得ることができますが、結合は含まれません。

SELECT
  ID,
  X,
  Y,
  RowAddedDate
FROM
  (
    SELECT
      *,
      MaxRowAddedDate = MAX(RowAddedDate) OVER (PARTITION BY X, Y)
    FROM
      dbo.MyTable
  ) AS derived
WHERE
  RowAddedDate = MaxRowAddedDate
;

X、YごとのRowAddedDateの最大値が、非集計値とともに返されます。最大値にフィルターをかけるだけで、必要な行を取得できます。

4
Andriy M

わかりました、これを投稿するとすぐに、頭が一瞬でした。それでも、答えは誰かを助けるかもしれません。

クエリ内のMAX(RowAddedDate), X, Yの組み合わせが一意ではない可能性があるため、クエリは行ごとに1つのIDを返すことを保証できません。

そのため、結合条件としてこれらの3つの値を使用して、テーブル自体をJOINする必要があります。

1
BanksySan