如果没有窗口函数,您可以自己排序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
根据我们所在的结果集(在 中跟踪@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
并且不需要显示)。