Я хочу написать запрос, который будет обновлять дубликаты для каждой группы:
INPUT
+-------+-------+
| group | name |
+-------+-------+
| 1 | name1 |
| 1 | name1 |
| 1 | name1 |
| 1 | name2 |
| 2 | name1 |
| 2 | name1 |
| 3 | name1 |
| 3 | name2 |
+-------+-------+
OUTPUT
+-------+----------------+
| group | name |
+-------+----------------+
| 1 | name1 |
| 1 | name1 - Copy 1 |
| 1 | name1 - Copy 2 |
| 1 | name2 |
| 2 | name1 |
| 2 | name1 - Copy 1 |
| 3 | name1 |
| 3 | name2 |
+-------+----------------+
Здесь есть что-то подобное. Переименование дубликатов данных в sql, но моя проблема заключается в том, как бороться с группами. Не так важно, как назвать эти дубликаты, но будет здорово, если я смогу сделать это, как указано в моем примере.
Если у вас есть столбец id
первичного ключа, попробуйте это:
update (
select 'group', name, min(id) as min_id
from test
group by 'group', name
) x
join test t using ('group', name)
set t.name =
case when t.id <> x.min_id
then concat(t.name, ' - Copy ', t.id - x.min_id)
else t.name
end
;
Демо: http://rextester.com/AWEX77086
Вот еще один способ, который, вероятно, медленнее, но гарантирует последовательные номера копий.
update (
select l.id, count(*) as copy_nr
from test l
join test r
on r.group = l.group
and r.name = l.name
and r.id < l.id
group by l.id
) x
join test t using (id)
set t.name = concat(t.name, ' - Copy ', x.copy_nr);
Это непроверено, но вы можете сгладить функцию LAG
которая видна во многих других СУБД с переменными (подробнее здесь).
Идея заключается в том, что вы сохраняете поля группы и имени и сравниваете их с ними перед их обновлением.
SET @RowNumber = 0;
SET @PreviousGroup = NULL;
SET @PreviousName = NULL;
SELECT
@PreviousGroup AS PreviousGroup,
@PreviousName AS PreviousName,
CASE
WHEN @PreviousGroup = 'group' AND @PreviousName = 'name' THEN (@RowNumber := @RowNumber + 1)
ELSE @RowNumber := 0
END AS 'Counter',
CASE
WHEN @PreviousGroup = 'group' AND @PreviousName = 'name' THEN CONCAT('name','- Copy ',@RowNumber)
ELSE 'name'
END AS 'Name',
@PreviousGroup := 'group' AS RawGroup,
@PreviousName := 'name' AS RawName
FROM
tbl1
ORDER BY
'group' ASC,
'name' ASC;
Вы можете сделать это с помощью переменных. Я бы посоветовал:
set @i = 0;
set @gn := '';
update t
set name = concat_ws(' - Copy ', name,
nullif(if(@gn = concat_ws(':', group, name), @i := @i + 1,
if(@gn := concat_ws(':', group, name), @i := 1, @i := 1)
), 0)
order by t.group, name;
Попробуйте ниже, замените группы Группой.
Хорошо, мне было указано, что это вопрос MySQL, поэтому ниже не работает MySQL, но только для t-sql.
SELECT Groups,
CASE WHEN Duplicate > 1
THEN Name + ' - Copy ' + CONVERT(VARCHAR(10), Duplicate)
ELSE Name
END AS Name
FROM
(
SELECT Groups,
Name,
ROW_NUMBER() OVER(PARTITION BY Name, Groups ORDER BY Name ) As Duplicate
FROM TableName
) AS Data
ORDER BY Groups