MySQL的升序行号

时间:2014-11-12 05:57:47

标签: mysql

这个问题在Stackoverflow上问了很多,但是我遇到了一些不同的问题。

SET @rownum = 0; 
SELECT DISTINCT doc.id, 
                doc.created_date, 
                ( @rownum := @rownum + 1 ) AS rownumbers 
FROM   document AS doc 
       INNER JOIN document_type_master dt 
               ON doc.document_type_id = dt.id 
ORDER  BY doc.id ASC; 

以上查询为我提供了以下输出。

id      created_date         rownumbers
5664    2014-06-05 07:23:40  1
5665    2014-06-06 06:37:34  2
5666    2014-06-06 10:25:56  3
5667    2014-06-06 10:33:39  4
5668    2014-06-06 11:28:28  5

如果我将ORDER BY doc.id ASC更改为ORDER BY doc.id DESC,则输出为

id      created_date         rownumbers
6364    2014-11-11 17:57:04  691
6363    2014-11-11 11:09:49  690
6362    2014-11-11 10:58:34  689
6361    2014-11-10 17:39:47  688
6360    2014-11-10 16:59:53  687

我尝试了一些事情,发现如果我从查询中删除DISTINCT,则在rownumbers的情况下,1,2,3...会启动ORDER BY doc.id DESC

id      created_date         rownumbers
6364    2014-11-11 17:57:04  1
6363    2014-11-11 11:09:49  2
6362    2014-11-11 10:58:34  3
6361    2014-11-10 17:39:47  4
6360    2014-11-10 16:59:53  5

我也尝试过点rownumbers ORDER BY doc.id DESC, rownumbers ASC,但不适合我。

我希望rownumbers值始终为ASC顺序,无论我是否使用DISTINCT


更新

@Barmar是正确的,但如果我在rownumbers子句中使用WHERE,如

rownumbers between 1 and 5然后显示错误Error Code: 1054. Unknown column 'rownumbers' in 'where clause'

1 个答案:

答案 0 :(得分:2)

在生成结果中的所有行之后完成ORDER BY处理。首先,它通过按照数据库中的任何顺序处理数据来分配所有rownumber列,然后反向重新排序。

这种情况仅在您使用DISTINCT时才会发生,因为这需要它首先生成所有结果,以便它可以删除所有重复项。如果没有DISTINCT,它可以采用快捷方式并对原始表数据执行排序。然而,虽然这通常按预期工作,但不能保证。

要获得所需的结果,您需要将ORDER BY放入子查询中:

SET @rownum = 0;
SELECT x.*, ( @rownum := @rownum + 1 ) AS rownumbers 
FROM (
    SELECT DISTINCT doc.id, 
                    doc.created_date
    FROM   document AS doc 
           INNER JOIN document_type_master dt 
                   ON doc.document_type_id = dt.id 
    ORDER  BY doc.id DESC) AS x

要在WHERE子句中引用rownumbers,您需要另一级子查询:

SELECT *
FROM (
    SELECT x.*, ( @rownum := @rownum + 1 ) AS rownumbers 
    FROM (
        SELECT DISTINCT doc.id, 
                        doc.created_date
        FROM   document AS doc 
               INNER JOIN document_type_master dt 
                       ON doc.document_type_id = dt.id 
        ORDER  BY doc.id DESC) AS x
    ) AS y
WHERE rownumbers BETWEEN 1 AND 5

或者您可以使用HAVING

SELECT x.*, ( @rownum := @rownum + 1 ) AS rownumbers 
FROM (
    SELECT DISTINCT doc.id, 
                    doc.created_date
    FROM   document AS doc 
           INNER JOIN document_type_master dt 
                   ON doc.document_type_id = dt.id 
    ORDER  BY doc.id DESC) AS x
HAVING rownumbers BETWEEN 1 AND 5

但是当我尝试使用来自这样的变量的别名HAVING时,我看到了一些奇怪的行为,显然是因为MySQL采用了这些快捷方式。