2015-03-05 2 views
1

Я пытаюсь очистить некоторые некорректные данные:MySQL - обновление строки, в которых значение в столбце такой же, как предыдущий ряд

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, сохраняя при этом значения, где колонна предполагаемому стоимость?

ответ

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 | 
+----+------+------+------+ 

Теперь мы знаем, что наши идентификаторы, которые должны быть обновлены.
Но мы не можем запустить:

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 

но мы можем избежать этой ошибки, используя временную таблицу для идентификаторов:

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 | 
+----+------+ 
+0

насчет не подряд идентификаторы? – Mihai

+0

Это сработало отлично, спасибо. И спасибо за показ тестовых данных. – BadHorsie

+0

Добро пожаловать в любое время) –

0

Пользовательские переменные, чтобы имитировать номер строки на каждый name.Tested на моей машине

SELECT @var:=name,@no:=0 FROM t ORDER BY id; 
UPDATE t join 
(select ID,NAME,(CASE WHEN [email protected] THEN @no:[email protected]+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 
0

У меня есть очень простой и прямой вперед решение.

Просто получите первую запись каждого, игнорируйте ее в обновлении. Завещание запрос выглядит следующим образом:

UPDATE table SET name = NULL WHERE id NOT IN (SELECT id FROM table WHERE name = 'A' LIMIT 1) 
Смежные вопросы