Frånvarande fönsterfunktioner kan du beställa tbl
och använd användarvariabler för att själv beräkna rang över dina partitioner ("datum"-värden):
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;
Uppdatera
Så, vad gör den frågan?
Vi använder användarvariabler att "loopa" genom en sorterad resultatuppsättning, öka eller nollställa en räknare (@rank
) beroende på vilket sammanhängande segment av resultatuppsättningen (spåras i @partition
) vi är med.
I fråga A vi initierar två användarvariabler. I fråga B vi får posterna för ditt bord i den ordning vi behöver:först efter datum och sedan efter värde. A och B gör tillsammans en härledd tabell, tbl_ordered
, som ser ut ungefär så här:
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
Kom ihåg att vi egentligen inte bryr oss om kolumnerna dummy.rank
och dummy.partition
— de är bara slumpen av hur vi initierar variablerna @rank
och @partition
.
I fråga C vi går igenom den härledda tabellens poster. Vad vi gör är mer eller mindre vad följande pseudokod gör:
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)
Till sist, fråga D projicerar alla kolumner från C förutom för kolumnen som innehåller @partition
(som vi döpte till dummy
och behöver inte visas).