Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mysql中的组内排序_Mysql_Sql_Sorting_Rank_Percentile - Fatal编程技术网

mysql中的组内排序

mysql中的组内排序,mysql,sql,sorting,rank,percentile,Mysql,Sql,Sorting,Rank,Percentile,我有一个面板数据集:即,时间,ID,和值。我想做一个排名的基础上的价值为每个日期。我只需运行以下命令即可实现排序: select * from tbl order by date, value 我的问题是,一旦表格以这种方式排序,我如何检索每个组的行号(也就是说,对于每个日期,我希望有一个名为ranking的列,从1到N) 例如: 输入: Date, ID, Value d1, id1, 2 d1, id2, 1 d2, id1, 10 d2, id2, 11 输出: Date, I

我有一个面板数据集:即,
时间
ID
,和
。我想做一个排名的基础上的价值为每个日期。我只需运行以下命令即可实现排序:

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

这会奏效吗

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 

如果没有窗口函数,您可以自己排序
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;
更新 那么,这个查询在做什么

我们使用用户变量“循环”经过排序的结果集,根据结果集的哪个连续段(在
@partition
中跟踪),递增或重置计数器(
@rank

在查询A中,我们初始化两个用户变量。在查询B中,我们按照需要的顺序获取表的记录:首先按日期,然后按值AB一起构成一个派生表,
tbl_排序
,看起来像这样:

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
时的意外情况

在queryC中,我们循环遍历派生表的记录。我们所做的或多或少是以下伪代码所做的:

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)

最后,queryDC投影所有列,除了包含
@partition
的列(我们将其命名为
dummy
,不需要显示)。

我知道这是一个老问题,但这里有一个简短的答案:

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

请不要在SQL保留字后面命名列,例如DATE,即使出于说明目的。不,DATE不是保留字(因为有太多人滥用它,mysql允许DATE为非保留字)@ajreal:@pilcrow可能意味着
DATE
是标准的SQL保留字吗?我的意思是,我不确定是否有这样的东西。即使没有保留,使用
date
time
作为列名表也是不好的做法。与
DATE()
函数或
DATE
数据类型混淆太多。--
MySQL允许将一些关键字用作不带引号的标识符,因为许多人以前使用过它们。示例如下所示:…
对于有关SQL Server的问题,您可以保留这样的答案。(尽管我必须说,您也应该更加注意您所回答的问题:分区应该在
日期
之前完成,而不是在
ID
之前完成,并且排序更可能是通过
而不是通过任何其他方式完成的。)谢谢您。我正试图理解这个问题,但它有点复杂。你能对这里发生的事情做一点评论吗?谢谢你的帮助。解释得很清楚。。非常适合没有像我这样丰富SQL经验的人!绝妙的方法!重命名虚拟表中的分区attr,因为MySQL将变得混乱。-“@partition:=NULL作为分区”谢谢,@ninjabber。这种手动分区很快就会变得笨拙——当您想要基于三个或更多标准进行分区时,您会严重错过窗口/分析功能——但对于这个问题来说,它已经足够好了。