【MySQL】MySQL數據庫如何生成分組排序的序號

2024年2月6日 19点热度 0人点赞

在MySQL8.0中可以使用窗口函數來實現,可以參考歷史文章有了這些函數,統計分析事半功倍進行了解。而MySQL5.7中由於沒有這類函數,該如何實現呢,下面對比MySQL8.0,列舉兩種情況的實現。

經常進行數據分析的小夥伴經常會需要生成序號或進行數據分組排序並生成序號。在MySQL8.0中可以使用窗口函數來實現,可以參考歷史文章有了這些函數,統計分析事半功倍進行了解。而MySQL5.7中由於沒有這類函數,該如何實現呢,下面對比MySQL8.0,列舉兩種情況的實現。

1、數據準備

創建一張演示表:

#創建表
CREATE TABLE users (
  id INT PRIMARY KEY,
  group_id INT,
  c_name VARCHAR(64)
);

插入演示數據:

-- 插入10行數據
INSERT INTO users VALUES (1, 1, '張三');
INSERT INTO users VALUES (2, 1, '李四');
INSERT INTO users VALUES (3, 2, '王五');
INSERT INTO users VALUES (4, 2, '趙六');
INSERT INTO users VALUES (5, 3, '錢七');
INSERT INTO users VALUES (6, 1, '周八');
INSERT INTO users VALUES (7, 2, '吳九');
INSERT INTO users VALUES (8, 3, '鄭十');
INSERT INTO users VALUES (9, 1, '孫十一');
INSERT INTO users VALUES (10, 3, '李十二');

2、生成序號

(1)使用窗口函數ROW_NUMBER()實現

在MySQL8.0中可以直接使用窗口函數ROW_NUMBER()來實現序號的生成,例如:

# 根據c_name字段進行排序生成序號
SELECT
  ROW_NUMBER() OVER (ORDER BY c_name) AS row_num,
  id,
  c_name
FROM
users;

結果如下:

 --------- ---- ----------- 
| row_num | id | c_name    |
 --------- ---- ----------- 
|       1 |  7 | 吳九      |
|       2 |  6 | 周八      |
|       3 |  9 | 孫十一    |
|       4 |  1 | 張三      |
|       5 | 10 | 李十二    |
|       6 |  2 | 李四      |
|       7 |  3 | 王五      |
|       8 |  4 | 趙六      |
|       9 |  8 | 鄭十      |
|      10 |  5 | 錢七      |
 --------- ---- ----------- 
10 rows in set, 1 warning (0.00 sec)

(2)低版本MySQL中的實現

因為在MySQL8.0版本之前無ROW_NUMBER()窗口函數,因此需要結束變量來實現。具體示例如下:

SET @row_num = 0;
SELECT
  (@row_num:=@row_num   1) AS row_num,
  id,
 c_name
FROM
  users
ORDER BY
  c_name;

結果如下:

 --------- ---- ----------- 
| row_num | id | c_name    |
 --------- ---- ----------- 
|       1 |  7 | 吳九      |
|       2 |  6 | 周八      |
|       3 |  9 | 孫十一    |
|       4 |  1 | 張三      |
|       5 | 10 | 李十二    |
|       6 |  2 | 李四      |
|       7 |  3 | 王五      |
|       8 |  4 | 趙六      |
|       9 |  8 | 鄭十      |
|      10 |  5 | 錢七      |
 --------- ---- ----------- 
10 rows in set, 1 warning (0.00 sec)

註意:每次執行前需要將@row_num重新設置為0 ,即執行SET @row_num = 0。

3、分組後排序

(1)繼續使用窗口函數ROW_NUMBER()實現

在MySQL8.0中可以繼續使用窗口函數ROW_NUMBER()來實現分組排序的功能,例如:

SELECT
  id,
  group_id,
  c_name,
  ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY id) AS row_num
FROM
  users
ORDER BY
  group_id, id;

運行結果如下:

 ---- ---------- ----------- --------- 
| id | group_id | c_name    | row_num |
 ---- ---------- ----------- --------- 
|  1 |        1 | 張三      |       1 |
|  2 |        1 | 李四      |       2 |
|  6 |        1 | 周八      |       3 |
|  9 |        1 | 孫十一    |       4 |
|  3 |        2 | 王五      |       1 |
|  4 |        2 | 趙六      |       2 |
|  7 |        2 | 吳九      |       3 |
|  5 |        3 | 錢七      |       1 |
|  8 |        3 | 鄭十      |       2 |
| 10 |        3 | 李十二    |       3 |
 ---- ---------- ----------- --------- 
10 rows in set (0.00 sec)

(2)低版本MySQL中的實現

因為涉及到分組及分組後排序,因此需要引入2個變量,一個用於分組標識,一個用於組內排序標識,示例如下:

SET @row_num = 0;
SET @g_id = NULL;
SELECT
  id,
  group_id,
  c_name,
  @row_num := CASE
                  WHEN @g_id = group_id THEN @row_num   1
                  ELSE 1
                END AS row_num,
  @g_id := group_id AS v_gid
FROM
  users
ORDER BY
  group_id, id;

運行結果如下:

 ---- ---------- ----------- --------- ------- 
| id | group_id | c_name    | row_num | v_gid |
 ---- ---------- ----------- --------- ------- 
|  1 |        1 | 張三      |       1 |     1 |
|  2 |        1 | 李四      |       2 |     1 |
|  6 |        1 | 周八      |       3 |     1 |
|  9 |        1 | 孫十一    |       4 |     1 |
|  3 |        2 | 王五      |       1 |     2 |
|  4 |        2 | 趙六      |       2 |     2 |
|  7 |        2 | 吳九      |       3 |     2 |
|  5 |        3 | 錢七      |       1 |     3 |
|  8 |        3 | 鄭十      |       2 |     3 |
| 10 |        3 | 李十二    |       3 |     3 |
 ---- ---------- ----------- --------- ------- 
10 rows in set, 2 warnings (0.00 sec)

這樣就實現了分組及排序的序號生成。

--END--

歡迎關註【輝哥傳書vlog】頭條號,喜歡記得點贊、收藏、評論、轉發哦!