Funções de janela ausentes, você pode solicitar
tbl
e use variáveis de usuário para calcular a classificação sobre suas partições (valores de "data"):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;
Atualizar
Então, o que essa consulta está fazendo?
Estamos usando variáveis de usuário para "loop" através de um conjunto de resultados ordenado, incrementando ou redefinindo um contador (
@rank
) dependendo de qual segmento contíguo do conjunto de resultados (rastreado em @partition
) estavam em. Na consulta A inicializamos duas variáveis de usuário. Na consulta B obtemos os registros de sua tabela na ordem que precisamos:primeiro por data e depois por valor. A e B juntos fazem uma tabela derivada,
tbl_ordered
, que se parece com isso: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
Lembre-se, nós realmente não nos importamos com as colunas
dummy.rank
e dummy.partition
— são apenas acidentes de como inicializamos as variáveis @rank
e @partition
. Na consulta C fazemos um loop pelos registros da tabela derivada. O que estamos fazendo é mais ou menos o que o seguinte pseudocódigo faz:
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)
Por fim, consulte D projeta todas as colunas de C exceto para a coluna que contém
@partition
(que chamamos de dummy
e não precisa exibir).