我需要用顺序编号更新表格,但跳过已在使用的数字。
该表有 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
在上面的示例中,按钮 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。
解决了。
我的问题中的两个查询需要一些东西来将它们连接到 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 |
结果现在可以用来更新表格。