При отсутствии оконных функций вы можете заказать 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
) в зависимости от того, какой непрерывный сегмент результатаset (отслеживается в @partition
), в котором мы находимся.
В запросе A мы инициализируем две пользовательские переменные.В запросе B мы получаем записи вашей таблицы в нужном нам порядке: сначала по дате, а затем по значению. A и B вместе составляют производную таблицу, tbl_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
и dummy.partition
- это просто случайность того, как мы инициализируем переменные @rank
и @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
и не нужно отображать).