SQL: Переименовать повторяющиеся имена файлов, добавив 1,2,3 … перед расширением

#sql #duplicates #rename #increment

#sql #дубликаты #переименовать #увеличить

Вопрос:

Я пытаюсь выяснить, как переименовать содержимое столбца, в котором хранится имя файла. В настоящее время в этом поле есть дубликаты, которые я пытаюсь переименовать, добавив инкрементное целое число после каждого дубликата, например

 ID       | FILENAME
----------------------
1        | file1.ext
2        | file2.ext
3        | file1.ext
4        | file1.ext
5        | file3.ext
6        | file3.ext
7        | file4.ext
  

Итак, в приведенном выше примере я хочу, чтобы следующее было уникальным:

 ID       | FILENAME
----------------------
1        | file1.ext
3        | file1.ext
4        | file1.ext
5        | file3.ext
6        | file3.ext
  

Изменив имена файлов на:

 ID       | FILENAME
----------------------
1        | file1-1.ext
3        | file1-2.ext
4        | file1-3.ext
5        | file3-1.ext
6        | file3-2.ext
  

Я знаю, как найти дубликаты, но я не уверен, как добавить приращения непосредственно перед расширением или как увеличить количество в первую очередь.

Буду признателен за любую помощь.

Ответ №1:

Используйте функцию window row_number() для получения числа и replace для манипулирования строками.
Вы не раскрыли свою СУБД. Следующий запрос протестирован на PostgreSQL 9.0. MySQL не поддерживает оконные функции, в отличие от большинства других больших СУБД.

Переименуйте все имена файлов:

 SELECT id
      ,replace(filename, '.',  
               '-'
               || row_number() OVER (PARTITION BY filename ORDER BY id)
               || '.')
FROM   mytbl
  

Переименовывайте только повторяющиеся имена файлов:

 SELECT id
      ,CASE WHEN (count(*) OVER (PARTITION BY filename)) > 1 THEN
          replace(filename, '.',  
                  '-'
                  || row_number() OVER (PARTITION BY filename ORDER BY id)
                  || '.')
       ELSE filename END AS filename
FROM   mytbl;
  

Отредактируйте с дополнительными запрошенными функциями

Эта версия работает с несколькими точками в имени или без них. Протестировано в PostgreSQL 9.0.

 SELECT id
      ,CASE WHEN (count(*) OVER (PARTITION BY filename)) > 1 THEN
          regexp_replace(filename
              -- pick the longest string from the start not 
             ,'^([^.]*)'containing a '.'
              -- and replace it with itself   row_number
             ,E'\1-' || row_number() OVER (PARTITION BY filename ORDER BY id))
       ELSE filename END AS filename
FROM   mytbl
  

Комментарии:

1. Спасибо, Эрвин, я использую IBM DB2, и, похоже, вышеприведенное работает отлично. Просто чтобы добавить немного больше сложности 🙂 1. Некоторые файлы могут содержать ‘.’ в своем имени, а также расширение, например ‘some.file.ext’ 2. Некоторые файлы могут не иметь расширения. Нужно ли мне просто наращивать обращения?

2. @Brian Оптимальное управление строками в значительной степени зависит от фактического распределения имен файлов и функций, доступных в DB2. Я добавил другую версию, которая делает все, что вы упомянули в PostgreSQL 9.0