简体   繁体   English

MySQL - 每组包含行号的更新表

[英]MySQL - Update table with row number per group

Sample Data 样本数据

id  |  order_id  |  instalment_num  | date_due
---------------------------------------------------------
1   |  10000     |  1               | 2010-07-09 00:00:00
2   |  10000     |  1               | 2010-09-06 11:39:56
3   |  10001     |  1               | 2014-04-25 15:46:52
4   |  10002     |  1               | 2010-01-11 00:00:00
5   |  10003     |  1               | 2010-01-04 00:00:00
6   |  10003     |  1               | 2016-05-31 00:00:00
7   |  10003     |  1               | 2010-01-08 00:00:00
8   |  10003     |  1               | 2010-01-06 09:06:26
9   |  10004     |  1               | 2010-01-11 11:25:07
10  |  10004     |  1               | 2010-01-12 07:06:42

Desired Result 期望的结果

id  |  order_id  |  instalment_num  | date_due
---------------------------------------------------------
1   |  10000     |  1               | 2010-07-09 00:00:00
2   |  10000     |  2               | 2010-09-06 11:39:56
3   |  10001     |  1               | 2014-04-25 15:46:52
4   |  10002     |  1               | 2010-01-11 00:00:00
5   |  10003     |  1               | 2010-01-04 00:00:00
8   |  10003     |  2               | 2010-01-06 09:06:26
7   |  10003     |  3               | 2010-01-08 00:00:00
6   |  10003     |  4               | 2016-05-31 00:00:00
9   |  10004     |  1               | 2010-01-11 11:25:07
10  |  10004     |  2               | 2010-01-12 07:06:42

As you can see, I have an instalment_num column which should show the number/index of each row belonging to the order_id , determined by the date_due ASC, id ASC order. 如您所见,我有一个instalment_num列,它应该显示属于order_id的每一行的数量/索引,由date_due ASC, id ASC顺序确定。

How can I update the instalment_num column like this? 如何像这样更新instalment_num列?

Additional Notes 补充说明

  • The date_due column is not unique, and there may be many id s or order_id s with the exact same timestamp. date_due列不是唯一的,并且可能有许多idorder_id具有完全相同的时间戳。

  • If the timestamp is the same for two rows belonging to the same order_id , it should order them by id as a fallback. 如果属于同一order_id两行的时间戳相同,则它应按id作为后备顺序排序。

  • I require a query which will update this column. 我需要一个更新此列的查询。

This is how I would do it: 我就是这样做的:

SELECT a.id,
    a.order_id,
    COUNT(b.id)+1 AS instalment_num,
    a.date_due
FROM sample_data a
    LEFT JOIN sample_data b ON a.order_id=b.order_id AND (a.date_due>b.date_due OR (a.date_due=b.date_due AND a.id>b.id))
GROUP BY a.id, a.order_id, a.date_due
ORDER BY a.order_id, a.date_due, a.id

UPDATE version attempt: 更新版本尝试:

UPDATE sample_data
    LEFT JOIN (SELECT a.id,
    COUNT(b.id)+1 AS instalment_num
FROM sample_data a
    JOIN sample_data b ON a.order_id=b.order_id AND (a.date_due>b.date_due OR (a.date_due=b.date_due AND a.id>b.id))
GROUP BY a.id) c ON c.id=sample_data.id
SET sample_data.instalment_num=c.instalment_num

For the numbering to begin with 1: 对于以1开头的编号:

UPDATE sample_data
    LEFT JOIN (SELECT a.id,
    COUNT(b.id) AS instalment_num
FROM sample_data a
    JOIN sample_data b ON a.order_id = b.order_id AND (a.date_due > b.date_due OR (a.date_due=b.date_due AND a.id + 1 > b.id))
GROUP BY a.id) c ON c.id = sample_data.id
SET sample_data.instalment_num = c.instalment_num

You are trying to achieve what ROW_NUMBER with a partition would do using something like SQL Server or Oracle. 您正在尝试使用SQL Server或Oracle之类的东西来实现分区的ROW_NUMBER You can simulate this with an approriate query: 您可以使用适当的查询来模拟这个:

SELECT t.id, t.order_id,
(
    SELECT 1 + COUNT(*)
    FROM sampleData
    WHERE (date_due < t.date_due OR (date_due = t.date_due AND id < t.id)) AND
        order_id = t.order_id
) AS instalment_num,
    t.date_due
FROM sampleData t
ORDER BY t.order_id, t.date_due

This query will order the instalment_num by due_date in ascending order. 这个查询将责令instalment_num通过due_date升序排列。 And in the case of a tie in due_date , it will order by the id in ascending order. due_date中为tie的情况下,它将按id按升序排序。

Follow the link below for a demo: 请点击以下链接进行演示:

SQLFiddle SQLFiddle

select 
  sub.order_id, sub.date_due,
  @group_rn:= case 
              when @group_order_id=sub.order_id then @group_rn:=@group_rn:+1 
              else 1 
              end as instalment_num,
  @group_order_id:=sub.order_id
FROM (select @group_rn:=0, group_order_id=0) init, 
     (select * 
      from the_table
      order by order_id, date_due) sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM