2

我有一个面板数据集:即timesidsvalues。我想根据每个日期的价值进行排名。我可以通过运行非常简单地实现排序:

select * from tbl order by date, value

我遇到的问题是,一旦表格以这种方式排序,我如何检索每个组的行号(也就是说,对于每个日期,我希望有一个名为排名的列,从 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
4

3 回答 3

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根据我们所在的结果集(在 中跟踪@partition)的哪个连续段来递增或重置计数器()。

在查询A中,我们初始化了两个用户变量。在查询B中,我们按我们需要的顺序获取表的记录:首先按日期,然后按值。 AB一起创建了一个派生表 ,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.rankdummy.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并且不需要显示)。

于 2011-12-06T05:35:25.513 回答
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
于 2013-03-20T12:33:58.800 回答
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 
于 2011-12-06T01:46:05.157 回答