#mysql #sql #google-cloud-platform
#mysql #sql #google-облачная платформа
Вопрос:
У меня есть таблица из 433 333 записей в базе данных MySQL в Google Cloud, которая выглядит примерно так:
Album_ID | Track_Len | Track_Name | Ft_LName1 | Ft_FName1 | Ft_LName2 | Ft_FName2 | Ft_LName3 | Ft_FName3 | Row_Num |
--------- ----------- --------------------------------------- ----------- ----------- ----------- ----------- ----------- ----------- ---------
| N40781 | 5.19 | Tumbala (Da Lata Remix) | NULL | Novalima | NULL | NULL | NULL | NULL | 1 |
| N40781 | 5.01 | Ruperta (Zeb Remix) | NULL | Novalima | NULL | NULL | NULL | NULL | 2 |
| N40781 | 6.35 | Coba Guarango (Toni Economides Remix) | NULL | Novalima | NULL | NULL | NULL | NULL | 3 |
| B15033 | 6.02 | II-V-P | Quartet | ARC | NULL | NULL | NULL | NULL | 4 |
| N32395 | 4.47 | My Babe | Stigers | Curtis | NULL | NULL | NULL | NULL | 5 |
| N32395 | 5.13 | Thats All Right | Stigers | Curtis | NULL | NULL | NULL | NULL | 6 |
Обратите внимание, что первичный ключ должен быть (Album_ID,Track_Name).
Дубликатов много, поэтому я запускаю следующее, чтобы попытаться их устранить:
delete from Track where (Album_ID, Track_Name, Row_Num) IN(
select Album_ID, Track_Name, MAX(Row_Num)
from (select Album_ID,Track_Name,Row_Num from Track) as x
where (Album_ID, Track_Name) IN(
select Album_ID,Track_Name
from (select Album_ID,Track_Name from Track) as y
group by Album_ID, Track_Name
having count(*) > 1
)
group by Album_ID,Track_Name);
Но это занимает слишком много времени и не удаляет все дубликаты сразу.
Есть предложения по оптимизации этого запроса??
------------ --------------------- ------ ----- --------- ----------------
| Field | Type | Null | Key | Default | Extra |
------------ --------------------- ------ ----- --------- ----------------
| Album_ID | varchar(6) | YES | | NULL | |
| Track_Len | decimal(4,2) | YES | | NULL | |
| Track_Name | varchar(100) | YES | | NULL | |
| Ft_LName1 | varchar(40) | YES | | NULL | |
| Ft_FName1 | varchar(40) | YES | | NULL | |
| Ft_LName2 | varchar(40) | YES | | NULL | |
| Ft_FName2 | varchar(40) | YES | | NULL | |
| Ft_LName3 | varchar(40) | YES | | NULL | |
| Ft_FName3 | varchar(40) | YES | | NULL | |
| Row_Num | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
------------ --------------------- ------ ----- --------- ----------------
Комментарии:
1. Пожалуйста, покажите нам полную схему для
Track
и ее индексы. И, пожалуйста, покажите намexplain
выходные данные для этого запроса.2. Поскольку
Track_Name
это может измениться, я бы предложил сделать первичный ключ простым автоматически увеличиваемым целым числом и вместо этого использовать уникальный индекс для обеспечения уникальности альбома / трека. Если вам нужно изменить название трека, ссылка не будет нарушена.3. Договорились, что уникальный индекс поможет. Но я не могу добавить его, пока в таблице существуют повторяющиеся записи.
Ответ №1:
Традиционный способ сделать это в MySQL использует JOIN
и GROUP BY
:
delete t
from Track t left join
(select tt.Album_ID, tt.Track_Name, min(tt.row_num) as min_row_num
from Track tt
group by tt.Album_ID, tt.Track_Name
) tt
on t.row_number = tt.min_row_num
where tt.min_row_num is null;
При этом используется тот факт, что id
является уникальным в целом и, вероятно, первичным ключом. Вы также можете указать это как:
delete t
from Track t join
(select tt.Album_ID, tt.Track_Name, min(tt.row_num) as min_row_num
from Track tt
group by tt.Album_ID, tt.Track_Name
) tt
on tt.Album_ID = t.Album_ID and
tt.Track_Name = t.Track_Name and
t.row_number > tt.min_row_num;
Ответ №2:
Поскольку Album_ID
и Track_Name
различают каждую строку от другой, попробуйте это с помощью self join:
delete t from Track t
inner join Track tt
where
tt.Album_ID = t.Album_ID and
tt.Track_Name = t.Track_Name and
tt.Row_Num < t.Row_Num
Комментарии:
1. ОШИБКА 1093 (HY000): Вы не можете указать целевую таблицу ‘t’ для обновления в предложении FROM.
2. Нужен ли мне псевдоним в подзапросе?
3. Нет, это просто Mysql, который не позволяет указать целевую таблицу для обновления. Если у меня будет выход, я вернусь.
4. Что произошло??