MySQL/MariaDB 更新计数器分组依据

标签 mysql mariadb

如何更新 number 列,使其计数为 1,2,3,4,... 然后当另一列 booking_id 更改时再次从 1 重新开始?

这是我到目前为止所得到的:

SET @pos := 0;
SET @last := 0;

UPDATE booking_segments
SET number = (SELECT @pos := if(booking_id = @last, @pos + 1, 1)), @last := booking_id
where 1
ORDER BY booking_id, pickup_time_utc;

我认为这样的事情应该可行,但我不知道如何在不产生语法错误的情况下消除其中的 @last := booking_id 位。如果 MySQL 和像 JS 这样的逗号运算符,我可以做到,但我不确定 SET block 中还有什么可能有效。


我想通了,但是有没有更简单的方法来做到这一点?

SET @pos := 0;
SET @last := 0;

UPDATE booking_segments
SET number = @tmp := (SELECT @pos := if(booking_id = @last, @pos + 1, 1)),
    number = @last := booking_id, 
    number = @tmp
where 1
ORDER BY booking_id,pickup_time_utc ;

Here's the result如果您无法想象这一点。

+----+------------+--------+---------------------+
| id | booking_id | number | pickup_time_utc     |
+----+------------+--------+---------------------+
| 3  | 2          | 1      | 2015-02-22 18:00:00 |
+----+------------+--------+---------------------+
| 7  | 2          | 2      | 2015-02-23 04:00:00 |
+----+------------+--------+---------------------+
| 8  | 5          | 1      | 2015-06-06 21:00:00 |
+----+------------+--------+---------------------+
| 9  | 5          | 2      | 2015-06-07 08:15:00 |
+----+------------+--------+---------------------+
| 10 | 6          | 1      | 2015-04-11 15:00:00 |
+----+------------+--------+---------------------+
| 11 | 6          | 2      | 2015-04-12 05:30:00 |
+----+------------+--------+---------------------+
| 16 | 8          | 1      | 2015-07-28 08:20:00 |
+----+------------+--------+---------------------+
| 17 | 8          | 2      | 2015-07-28 10:00:00 |
+----+------------+--------+---------------------+
| 18 | 9          | 1      | 2015-07-01 15:50:00 |
+----+------------+--------+---------------------+
| 19 | 10         | 1      | 2015-09-13 06:00:00 |
+----+------------+--------+---------------------+
| 20 | 11         | 1      | 2015-08-01 23:30:00 |
+----+------------+--------+---------------------+
| 21 | 11         | 2      | 2015-08-02 07:00:00 |
+----+------------+--------+---------------------+
| 22 | 12         | 1      | 2015-08-08 20:00:00 |
+----+------------+--------+---------------------+
| 23 | 13         | 1      | 2015-09-05 21:00:00 |
+----+------------+--------+---------------------+
| 24 | 14         | 1      | 2015-09-19 20:30:00 |
+----+------------+--------+---------------------+
| 25 | 15         | 1      | 2015-08-29 21:15:00 |
+----+------------+--------+---------------------+
| 26 | 16         | 1      | 2015-09-10 03:15:00 |
+----+------------+--------+---------------------+
| 37 | 16         | 2      | 2015-09-10 08:00:00 |
+----+------------+--------+---------------------+
| 28 | 17         | 1      | 2015-08-12 22:00:00 |
+----+------------+--------+---------------------+
| 29 | 18         | 1      | 2015-08-11 08:00:00 |
+----+------------+--------+---------------------+
| 30 | 19         | 1      | 2015-08-15 21:00:00 |
+----+------------+--------+---------------------+
| 32 | 20         | 1      | 2016-06-09 09:05:00 |
+----+------------+--------+---------------------+
| 31 | 20         | 2      | 2016-06-10 12:00:00 |
+----+------------+--------+---------------------+
| 33 | 21         | 1      | 2015-09-10 05:00:00 |
+----+------------+--------+---------------------+
| 34 | 22         | 1      | 2015-09-10 02:00:00 |
+----+------------+--------+---------------------+
| 35 | 22         | 2      | 2015-09-10 04:00:00 |
+----+------------+--------+---------------------+
| 36 | 22         | 3      | 2015-09-10 06:45:00 |
+----+------------+--------+---------------------+
| 38 | 23         | 1      | 2015-09-10 04:00:00 |
+----+------------+--------+---------------------+
| 39 | 23         | 2      | 2015-09-10 09:45:00 |
+----+------------+--------+---------------------+
| 40 | 24         | 1      | 2015-09-10 04:30:00 |
+----+------------+--------+---------------------+
| 41 | 24         | 2      | 2015-09-10 06:45:00 |
+----+------------+--------+---------------------+
| 67 | 38         | 1      | 2016-01-02 16:20:00 |
+----+------------+--------+---------------------+
| 68 | 38         | 2      | 2016-01-03 07:00:00 |
+----+------------+--------+---------------------+
| 69 | 38         | 3      | 2016-01-03 10:00:00 |
+----+------------+--------+---------------------+

我目前使用的版本是 10.1.14-MariaDB。

最佳答案

MariaDB started supporting Window/Analytic functions since version 10.2 ;所以如果你可以升级,你可以利用 Row_Number()功能。

在派生表中,我们可以首先获取每一行的“行号”,在 booking_id 的分区上按 pickup_time_utc 升序排列。然后我们可以连接回主表,以更新 number 列。查询将简单如下:

UPDATE booking_segments AS bs
       JOIN (SELECT id,
                    Row_number()
                      OVER (
                        partition BY booking_id
                        ORDER BY pickup_time_utc ASC) AS rn
             FROM   booking_segments) AS dt
         ON dt.id = bs.id
SET    bs.number = dt.rn  

关于MySQL/MariaDB 更新计数器分组依据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57602647/

相关文章:

mysql - 无法正常启动Mariadb?

mysql - 选择具有相同列的所有行以分隔 mysql 中的列

php - 将整个 SQL 数据库放入 HTML 表中

php - 将行号和奇/偶类添加到 php 表

php - PHP 中的服务器端级联下拉菜单

mysql - MySQL 中的 SCHEDULE 每分钟

php - 高分 - 用户的最佳时间段

php - 无法将 php 页面转换为 PDF

php - 使用 PHP PDO 和 MySQL 数据库进行批量获取的最快方法

mysql - LOAD DATA INFILE 在 mariadb 中不起作用