Funciones de ventana ausentes, puede ordenar tbl
y use variables de usuario para calcular el rango sobre sus particiones (valores de "fecha") usted mismo:
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;
Actualizar
Entonces, ¿qué está haciendo esa consulta?
Estamos usando variables de usuario para "recorrer" un conjunto de resultados ordenados, incrementando o restableciendo un contador (@rank
) según el segmento contiguo del conjunto de resultados (seguido en @partition
) estamos adentro.
En consulta A inicializamos dos variables de usuario. En consulta B obtenemos los registros de su tabla en el orden que necesitamos:primero por fecha y luego por valor. A y B juntos hacen una tabla derivada, tbl_ordered
, que se parece a esto:
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
Recuerde, realmente no nos importan las columnas dummy.rank
y dummy.partition
— son solo accidentes de cómo inicializamos las variables @rank
y @partition
.
En consulta C recorremos los registros de la tabla derivada. Lo que estamos haciendo es más o menos lo que hace el siguiente pseudocódigo:
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)
Finalmente, consulta D proyecta todas las columnas desde C excepto para la columna que contiene @partition
(que llamamos dummy
y no es necesario mostrar).