Переименование дубликатов на группу в sql

0

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

  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, но моя проблема заключается в том, как бороться с группами. Не так важно, как назвать эти дубликаты, но будет здорово, если я смогу сделать это, как указано в моем примере.

  • 0
    SQL - неупорядоченный набор. Без использования предложения ORDER BY MySQL может возвращать записи в произвольном порядке. Важен ли порядок переименования в этом случае? Если это важно, у alteast есть столбец, в котором мы можем определить естественный порядок, например столбец с первичным ключом с параметром auto_increment или столбец datetime с параметром defualt current_timestamp
  • 1
    Порядок вывода не важен. Но я хочу, чтобы все дубликаты внутри одной группы были переименованы.
Показать ещё 1 комментарий
Теги:

4 ответа

2
Лучший ответ

Если у вас есть столбец 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);

Демо: http://rextester.com/NWSF57017

  • 0
    Хорошая находка, но этот ответ потребует возрастающих идентификаторов в группе без дыр в идентификаторах
  • 0
    @RaymondNijland Это правда, но: «Не так важно, как назвать эти дубликаты».
Показать ещё 1 комментарий
1

Это непроверено, но вы можете сгладить функцию 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;
1

Вы можете сделать это с помощью переменных. Я бы посоветовал:

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;
1

Попробуйте ниже, замените группы Группой.

Хорошо, мне было указано, что это вопрос 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

Изображение 174551

  • 0
    Вы предполагаете, MySQL 8.x
  • 2
    Вопрос помечен MySQL. MySQL не поддерживает оконные функции до тех пор, пока MySQL 8.0+ не будет готовым к использованию. Поэтому я сомневаюсь, что топикстартер использует MySQL 8.0+
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню