我有一个面板数据集:即times
,ids
和values
。我想根据每个日期的值进行排名。我可以通过运行来简单地实现这种排序:
select * from tbl order by date, value
我遇到的问题是,一旦表以这种方式排序,我如何检索每个组的行号(也就是说,对于每个日期,我希望有一个名为rank的列,从1到N )。
示例:
输入:
Date, ID, Value
d1, id1, 2
d1, id2, 1
d2, id1, 10
d2, id2, 11
输出:
Date, ID, Value, Rank
d1, id2, 1, 1
d1, id1, 2, 2
d2, id1, 10, 1
d2, id2, 11, 2
答案 0 :(得分:3)
缺少窗口函数,您可以订购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
),具体取决于结果集的哪个连续段(在{中跟踪) {1}})我们在。
在查询 A 中,我们初始化两个用户变量。在查询 B 中,我们按照我们需要的顺序获取您的表的记录:首先按日期,然后按值。 A 和 B 一起制作派生表@partition
,如下所示:
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
的事故。< / p>
在查询 C 中,我们遍历派生表的记录。我们正在做的事情或多或少是以下伪代码的作用:
@partition
最后,查询 D 会为 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)
(我们将其命名为{{1}并且不需要显示)。
答案 1 :(得分:1)
我知道这是一个老问题,但这是一个较短的答案:
SELECT w.*, if(
@preDate = w.date,
@rank := @rank + 1,
@rank := (@preDate :=w.date) = w.date
) rank
FROM tbl w
JOIN (SELECT @preDate := '' )a
ORDER BY date, value
答案 2 :(得分:0)
这可以解决这个问题吗?
select [DATE],ID,Value,
(DENSE_RANK() OVER (
PARTITION BY ID
ORDER BY Date) )AS [DenseRank],
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY [Date] DESC) AS RN
from SomeTable