如何为组中的每一行分配顺序值

How to Assign Sequential Value to Each Row in a Group

提问人:Chris 提问时间:12/22/2022 更新时间:12/22/2022 访问量:104

问:

我有一个MySQL表,其中包含两个组(水果和动物)的数据,我需要在每个组中分配一个从1开始的顺序值

数据的初始状态为:

Fruit   Apple   NULL
Fruit   Orange  NULL
Fruit   Banana  NULL
Animal  Dog     NULL
Animal  Cat     NULL
Animal  Horse   NULL

期望的结果是:

Fruit   Apple   1
Fruit   Orange  2
Fruit   Banana  3
Animal  Dog     1
Animal  Cat     2
Animal  Horse   3

(结果是否按字母顺序排列并不重要;只是每组中有一个从 1 开始的唯一数字)

到目前为止,我已经能够为整个表中的每一行分配一个顺序值(即,范围从 1 到 6),但我想请教如何在组从“水果”变为“动物”时将计数器重置回 1

设置如下:

CREATE TABLE TempData (GroupName VARCHAR(16), ItemName VARCHAR(16), Sequence INT );
INSERT INTO TempData VALUES ('Fruit','Apple',NULL), ('Fruit','Orange',NULL), ('Fruit','Banana',NULL), ('Animal','Dog',NULL), ('Animal','Cat',NULL), ('Animal','Horse',NULL);

这是我目前的剧本

UPDATE TempData
INNER JOIN (  SELECT GroupName, ItemName, (@RowOrder := @RowOrder + 1) NewValue 
              FROM TempData
              INNER JOIN (SELECT @RowOrder := 0) VariableSet ) RowSequencing ON TempData.GroupName = RowSequencing.GroupName AND TempData.ItemName = RowSequencing.ItemName
SET TempData.Sequence = RowSequencing.NewValue;           

如果能帮助检测组名称何时更改,以便分配的序列号从 1 开始,我们将不胜感激。

谢谢

MySQL 序列

评论


答:

2赞 Tim Biegeleisen 12/22/2022 #1

如果您运行的是MySQL 8+,我建议您使用:ROW_NUMBER()

SELECT GroupName, ItemName,
       ROW_NUMBER() OVER (PARTITION BY GroupName ORDER BY ItemName) Sequence
FROM TempData
ORDER BY GroupName, ItemName;

我还建议不要将序列保存在实际的表列中。这是因为每次添加或删除数据时,顺序都会在逻辑上发生更改,这可能会迫使您再次更新。

如果必须进行更新,则可以使用更新联接:

UPDATE TempData t1
INNER JOIN
(
    SELECT GroupName, ItemName,
       ROW_NUMBER() OVER (PARTITION BY GroupName ORDER BY ItemName) rn
    FROM TempData
) t2
    ON t2.GroupName = t1.GroupName AND
       t2.ItemName = t1.ItemName
SET
    t1.Sequence = t2.rn;

评论

0赞 Chris 12/22/2022
这很好用,非常感谢。(我在MySQL 8.0.28上)。不幸的是,我有一个业务需求来存储顺序值,但从概念上讲,你所说的是完全有道理的。感谢您的协助!
0赞 Tim Biegeleisen 12/22/2022
如果你需要,我已经给了你一个更新选项。