顺序行更新,跳过有值的行

问题描述 投票:0回答:1

我需要用顺序编号更新表格,但跳过已在使用的数字。

该表有 3 个(重要)列:id、name 和 order,其中 order 是按钮的显示顺序。当空的时候,它看起来像这样:

id 某个名称 订单号
1 1
2 2
3 3
...
10 10

用户可以填写名称(或将其留空),但也可以更改按钮的顺序,甚至是空的按钮。保存数据后,我最终得到这样的结果:

id 某个名称 订单号
1 6
2 红色 5
3 8
4 9
5 蓝色 3
6 4
7 1
8 黄色 7
9 10
10 2
CREATE TABLE my_table(id tinyint(1),order_number tinyint(1),some_name varchar(40));
INSERT INTO my_table (id, order_number, some_name) VALUES
(1,6,NULL),(2,5,"red"),(3,8,NULL),(4,9,NULL),(5,3,"blue"),(6,4,NULL),(7,1,NULL),(8,7,"yellow"),(9,10,NULL),(10,2,NULL);

我喜欢做的是以这样的方式重新编号 order_numbers

  • 如果 name not null,保留用户选择的 order_number
  • 如果名称为空,则重新编号为尽可能小的增量数字
  • 对空值重新编号应该从最低到最高 id

在上面的示例中,按钮 2、5 和 8 有一个名称,因此我保留它们的顺序号(5、3、7)。其他的应该从 1 重新编号到 10(按 id 排序),跳过正在使用的 order_numbers。最后表格应该是这样的:

id 某个名称 订单号 (为什么) (下一个序列号)
1
1 1 名称为空,使用下一个:1 +1 = 2
2 红色 5 已满,保留5号 2
3 2 空,接下来使用:2 +1 = 3 :用于 id=5 -> +1 = 4
4 4 空,接下来使用:4 +1 = 5 :用于 id=2 -> +1 = 6
5 蓝色 3 已满,保留3号 6
6 6 空,接下来使用:6 +1 = 7 :用于 id=8 -> +1 = 8
7 8 空,接下来使用:8 +1 = 9
8 黄色 7 已满,保留7号 9
9 9 空,接下来使用:9 +1 = 10
10 10 空,接下来使用:10 +1 = 11

选择 id 的位置 name = null 不是问题:

SELECT id FROM my_table WHERE some_name IS NULL

结果:1、3、4、6、7、9、10(id 3、5、8 保留其 order_number)

另外,选择未使用的顺序 order_numbers:

SELECT NR.new_number
FROM
(
  select @ordnum := @ordnum + 1 as new_number
  FROM my_table,(select @ordnum := 0) r
  ORDER BY new_number LIMIT 10
) NR
LEFT JOIN 
(
  SELECT order_number FROM my_table 
  WHERE some_name IS NULL
) RO
ON(RO.order_number = NR.new_number)
WHERE RO.order_number IS NOT NULL
ORDER BY NR.new_number

结果:1,2,4,6,8,9,10(使用数字3,5,7)

问题是如何连接这两个查询(除了给出相同长度的结果集之外,它们没有任何共同点),以便它选择第一个 id 和第一个 order_number,更新,然后从每个查询中选择第二行,更新等等。到目前为止,我尝试过的每种 JOIN 要么给我 id,但顺序编号停留在 1,要么它针对每个 order_number 运行每个 id,导致每个 id 的 order_number = 10。

mariadb sequential
1个回答
0
投票

解决了。

我的问题中的两个查询需要一些东西来将它们连接到 JOIN 中。将它们都包装在一个新的 SELECT 中,并为两者添加一个计数器。现在他们可以在计数器上连接,这对于两个查询来说是相同的(因为两个查询都过滤相同的内容:名称为空的行)。

SELECT 
    /* result */
    empty_names.id,
    new_order.new_number
SELECT 
    @s1:=@s1+1 AS sq,
    id 
FROM(
    /* QUERY 1 goes here */
) AS empty_names
INNER JOIN
(
    SELECT 
        @s2:=@s2+1 AS sq,
        Y.new_number
    FROM(
        /* QUERY 2 goes here */
    ) Y,
    (select @s2:=0) s2
) new_order
/* connect on the counter */
ON empty_names.sq = new_order.sq
查询1 查询2 结果
序列 1 id 序列2 新号码 id 新号码
1 1 1 1 1 1
2 3 2 2 3 2
3 4 3 4 4 4
4 6 4 6 6 6
5 7 5 8 7 8
6 9 6 9 9 9
7 10 7 10 10 10

结果现在可以用来更新表格。

© www.soinside.com 2019 - 2024. All rights reserved.