ウィンドウ関数がない場合、tbl
ユーザー変数を注文して使用して、パーティション (「日付」値) のランクを自分で計算できます。
SELECT "date", -- D) Desired columns
id,
value,
rank
FROM (SELECT "date", -- C) Rank by date
id,
value,
CASE COALESCE(@partition, "date")
WHEN "date" THEN @rank := @rank + 1
ELSE @rank := 1
END AS rank,
@partition := "date" AS dummy
FROM (SELECT @rank := 0 AS rank, -- A) User var init
@partition := NULL AS partition) dummy
STRAIGHT_JOIN
( SELECT "date", -- B) Ordering query
id,
value
FROM tbl
ORDER BY date, value) tbl_ordered;
アップデート
では、そのクエリは何をしているのでしょうか。
ユーザー変数を使用して、並べ替えられた結果セットを「ループ」し、@rank
現在の結果セット ( で追跡) のどの連続セグメントに応じてカウンター ( )をインクリメントまたはリセットし@partition
ます。
クエリAでは、2 つのユーザー変数を初期化します。クエリBでは、必要な順序でテーブルのレコードを取得します。最初は日付順、次に値順です。 AとBtbl_ordered
を組み合わせて、次のような派生テーブル を作成します。
rank | partition | "date" | id | value
---- + --------- + ------ + ---- + -----
0 | NULL | d1 | id2 | 1
0 | NULL | d1 | id1 | 2
0 | NULL | d2 | id1 | 10
0 | NULL | d2 | id2 | 11
dummy.rank
列andについてはあまり気にしていないことを思い出してくださいdummy.partition
— それらは、変数@rank
andを初期化する方法の単なる偶然です@partition
。
クエリCでは、派生テーブルのレコードをループします。私たちがやっていることは、多かれ少なかれ、次の疑似コードが行うことです:
rank = 0
partition = nil
foreach row in fetch_rows(sorted_query):
(date, id, value) = row
if partition is nil or partition == date:
rank += 1
else:
rank = 1
partition = date
stdout.write(date, id, value, rank, partition)
最後に、クエリDは、 C からすべての列を射影しますが、保持している列(名前が付けられており、表示する必要はありません)を除きます。@partition
dummy