Brak funkcji okna, możesz zamówić tbl
i użyj zmiennych użytkownika do samodzielnego obliczenia rangi na partycjach (wartości "dat"):
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;
Aktualizacja
Co więc robi to zapytanie?
Używamy zmiennych użytkownika aby "zapętlić" posortowany zestaw wyników, zwiększając lub resetując licznik (@rank
) w zależności od ciągłego segmentu zestawu wyników (śledzonego w @partition
) jesteśmy w środku.
W zapytaniu A inicjujemy dwie zmienne użytkownika. W zapytaniu B otrzymujemy rekordy Twojej tabeli w potrzebnej kolejności:najpierw według daty, a następnie według wartości. A i B razem tworzą tabelę pochodną, tbl_ordered
, który wygląda mniej więcej tak:
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
Pamiętaj, że tak naprawdę nie dbamy o kolumny dummy.rank
i dummy.partition
— to tylko przypadki, jak inicjujemy zmienne @rank
i @partition
.
W zapytaniu C przechodzimy przez rekordy tabeli pochodnej. To, co robimy, jest mniej więcej tym, co robi następujący pseudokod:
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)
Na koniec wpisz zapytanie D wyświetla wszystkie kolumny z C z wyjątkiem dla kolumny zawierającej @partition
(które nazwaliśmy dummy
i nie trzeba ich wyświetlać).