我试图清理一些不正确的数据:
id | name
-------------
1 | C
2 | A
3 | A
4 | B
5 | B
6 | B
7 | B
8 | X
9 | X
10 | A
11 | A
12 | A
13 | X
14 | X
15 | B
16 | C
17 | C
18 | X
19 | A
20 | A
发生的事情是当输入数据时,如果name
字段为NULL,则前一次循环迭代的值尚未清除,因此已输入下一行。
数据应如下所示:
id | name
-------------
1 | C
2 | A
3 | NULL
4 | B
5 | NULL
6 | NULL
7 | NULL
8 | X
9 | NULL
10 | A
11 | NULL
12 | NULL
13 | X
14 | NULL
15 | B
16 | C
17 | NULL
18 | X
19 | A
20 | NULL
有没有办法可以通过将所有重复项设置为NULL来一次更新整个表,同时保留列具有预期值的值?
答案 0 :(得分:1)
我们需要将我们的副本加入到链中,通过以下方式轻松访问:
select *
from updateTable t1
left join updateTable t2 on t1.name = t2.name and t1.id+1 = t2.id
;
+----+------+------+------+
| id | name | id | name |
+----+------+------+------+
| 1 | C | NULL | NULL |
| 2 | A | 3 | A |
| 3 | A | NULL | NULL |
| 4 | B | 5 | B |
| 5 | B | 6 | B |
| 6 | B | 7 | B |
| 7 | B | NULL | NULL |
| 8 | X | 9 | X |
| 9 | X | NULL | NULL |
| 10 | A | 11 | A |
| 11 | A | 12 | A |
| 12 | A | NULL | NULL |
| 13 | X | 14 | X |
| 14 | X | NULL | NULL |
| 15 | B | NULL | NULL |
| 16 | C | 17 | C |
| 17 | C | NULL | NULL |
| 18 | X | NULL | NULL |
| 19 | A | 20 | A |
| 20 | A | NULL | NULL |
+----+------+------+------+
现在我们知道应该更新的ID。
但我们不能跑:
update updateTable set name = null where id in (
select t2.id
from updateTable t1
left join updateTable t2 on t1.name = t2.name and t1.id+1 = t2.id
where t2.id is not null
);
因为我们会收到错误:
ERROR 1093 (HY000): You can't specify target table 'updateTable' for update in FROM clause
但我们可以通过使用临时表来执行ID来避免此错误:
create temporary table updateTableTmp (
id int,
primary key (id)
) engine=innodb;
insert into updateTableTmp
select t2.id
from updateTable t1
left join updateTable t2 on t1.name = t2.name and t1.id+1 = t2.id
where t2.id is not null
;
update updateTable set name = null where id in (
select id from updateTableTmp
);
select * from updateTable;
+----+------+
| id | name |
+----+------+
| 1 | C |
| 2 | A |
| 3 | NULL |
| 4 | B |
| 5 | NULL |
| 6 | NULL |
| 7 | NULL |
| 8 | X |
| 9 | NULL |
| 10 | A |
| 11 | NULL |
| 12 | NULL |
| 13 | X |
| 14 | NULL |
| 15 | B |
| 16 | C |
| 17 | NULL |
| 18 | X |
| 19 | A |
| 20 | NULL |
+----+------+
答案 1 :(得分:0)
模仿每个名字的行号的用户变量。在我的机器上测试
SELECT @var:=name,@no:=0 FROM t ORDER BY id;
UPDATE t join
(select ID,NAME,(CASE WHEN NAME=@var THEN @no:=@no+1 ELSE @no:=1 AND @var:=NAME END) BLAH
from T
order by ID)X
on T.ID=X.ID
SET T.NAME= NULL
where X.BLAH<>0
答案 2 :(得分:0)
我有非常简单直接的解决方案。
只需获取每个记录的第一条记录,在更新时忽略它。 查询将如下所示:
UPDATE table SET name = NULL WHERE id NOT IN ( SELECT id FROM table WHERE name = 'A' LIMIT 1 )