MySQL - 在select上获取行号

Geo*_*rge 176 mysql sql row-number

如果项目已排序,我可以运行select语句并获取行号吗?

我有这样一张桌子:

mysql> describe orders;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| orderID     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| itemID      | bigint(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

然后我可以运行此查询以按ID获取订单数量:

SELECT itemID, COUNT(*) as ordercount
FROM orders
GROUP BY itemID ORDER BY ordercount DESC;
Run Code Online (Sandbox Code Playgroud)

这给了我itemID表中每个的计数如下:

+--------+------------+
| itemID | ordercount |
+--------+------------+
|    388 |          3 |
|    234 |          2 |
|   3432 |          1 |
|    693 |          1 |
|   3459 |          1 |
+--------+------------+
Run Code Online (Sandbox Code Playgroud)

我也想得到行号,所以我可以说这itemID=388是第一行,234是第二行等等(基本上是订单的排名,而不仅仅是原始计数).我知道当我得到结果集时,我可以在Java中执行此操作,但我想知道是否有一种方法可以纯粹在SQL中处理它.

更新

设置等级会将其添加到结果集中,但未正确排序:

mysql> SET @rank=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
    -> FROM orders
    -> GROUP BY itemID ORDER BY rank DESC;
+------+--------+------------+
| rank | itemID | ordercount |
+------+--------+------------+
|    5 |   3459 |          1 |
|    4 |    234 |          2 |
|    3 |    693 |          1 |
|    2 |   3432 |          1 |
|    1 |    388 |          3 |
+------+--------+------------+
5 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

Mik*_*icz 175

看看这个.

将您的查询更改为:

SET @rank=0;
SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC;
SELECT @rank;
Run Code Online (Sandbox Code Playgroud)

  • 看看swamibebop的答案 (9认同)
  • 尝试保留“ORDER BY ordercount DESC”,然后将整个查询包装在另一个“SELECT”中,该查询从第一个查询中获取所有内容,但按排名列排序(在本例中为 0)。 (2认同)
  • 你能举个例子吗?我将如何包装选择? (2认同)

小智 172

SELECT @rn:=@rn+1 AS rank, itemID, ordercount
FROM (
  SELECT itemID, COUNT(*) AS ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC
) t1, (SELECT @rn:=0) t2;
Run Code Online (Sandbox Code Playgroud)

  • 谁能解释`t1`和`t2`的相关性? (2认同)
  • @Jared,MySQL语法只需要一些东西.它可以是任何东西,甚至是`x`和`y`. (2认同)

Pac*_*ier 29

Swamibebop的解决方案有效,但通过利用table.*语法,我们可以避免重复内部的列名select并获得更简单/更短的结果:

SELECT @r := @r+1 , 
       z.* 
FROM(/* your original select statement goes in here */)z, 
(SELECT @r:=0)y;
Run Code Online (Sandbox Code Playgroud)

这样会给你:

SELECT @r := @r+1 , 
       z.* 
FROM(
     SELECT itemID, 
     count(*) AS ordercount
     FROM orders
     GROUP BY itemID
     ORDER BY ordercount DESC
    )z,
    (SELECT @r:=0)y;
Run Code Online (Sandbox Code Playgroud)


小智 11

您可以使用MySQL变量来执行此操作.这样的东西应该工作(但是,它包含两个查询).

SELECT 0 INTO @x;

SELECT itemID, 
       COUNT(*) AS ordercount, 
       (@x:=@x+1) AS rownumber 
FROM orders 
GROUP BY itemID 
ORDER BY ordercount DESC; 
Run Code Online (Sandbox Code Playgroud)

  • 小心,这行不通,因为 `order by` 发生在 ** 变量 `@x` 被求值之后。尝试通过使用其他列进行排序来进行试验。还可以同时试验 `desc` 和 `asc`。您会看到很多次它们会失败,并且只有在它起作用的时候,这是**纯粹的运气**,因为原始“选择”的顺序与“order by”的顺序相同。请参阅我的解决方案和/或 Swamibebop 的解决方案。 (2认同)

car*_*ram 6

它现在内置在 MySQL 8.0 和 MariaDB 10.2 中:

SELECT
  itemID, COUNT(*) as ordercount,
  ROW_NUMBER OVER (PARTITION BY itemID ORDER BY rank DESC) as rank
FROM orders
GROUP BY itemID ORDER BY rank DESC
Run Code Online (Sandbox Code Playgroud)