Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?) / 7 сообщений из 7, страница 1 из 1
09.10.2013, 02:05:35
    #38420994
InterSky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
Есть таблица X со связями:
idaabb10яяя24321яяя34322яяя40ыыыыы55050ыыыыы60юююююююю72345нету82345ййййййййй97111нету

В эту таблицу в идеальных условиях вносятся связи, например вторая строка: 4321,яяя (индекс с моделью)
Но иногда на момент ввода нету либо индекса (как например в первой строке, где: 0,яяя),
либо ещё нету самой модели (как например в седьмой строке, где: 2345, нету).
Однако в последсвии созаются новые индексы и приходят новые модели, и для первой строки появляется вторая, а для седьмой появляется восьмая (иногда индексов и моделей может быть несколько, например строки два и три).

Задача: выбросить неактуальные строки:
Строку №1, так как в строках 2 и 3 уже есть индексы для этой модели
Строку №4, так как в строке 5 уже есть индексы для этой модели
Строку №7, так как в строке 8 уже есть модель под этот индекс
при этом строка №6 является актуальной, так как под эту модель ещё не придуман индекс,
и строка №9 является актуальной, так как под данный индекс ещё нету модели.

Я деляю так: вначале путём группировки ищу одинаковые модели, и если нахожу то ищу в них записи с индексом "0",
а потом путём группировки ищу одинаковые индексы, и если нахожу то ищу в них записи с моделью "нету".

Выглядит это так:
Код: sql
1.
2.
select * from X where aa=0 and bb in (select bb from X group by bb having count(*)>1)
select * from X where bb='нету' and aa in (select aa from X group by aa having count(*)>1)



Ну и для удаления приходится делать так:
Код: sql
1.
2.
3.
4.
delete from X where
aa=0 and bb in (select bb (select bb from X group by bb having count(*)>1) as T1)
or
bb='нету' and aa in (select aa (select aa from X group by aa having count(*)>1) as T2)


*напомню что дополнительный (select aa ( ... ) as T1) приходится делать из-за особенности MySQL которая не даёт искать и удалять данные в одной таблице, и таким образом обходим это ограничение (MySQL думает что ищет данные не в таблице X, а в T1)

А вдруг кто-то может придумать как это сделать оптимальней?
...
Рейтинг: 0 / 0
09.10.2013, 06:00:21
    #38421026
Arhat109
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
InterSky,

?!? и так вполне нормально. Мне, так предпочтительнее, заменять IN(SELECT..) на JOIN-ы, типа и понятнее и чаще быстрее пашет. Можно сначалу впихнуть ваши выборки во времянки, а потом удалять всё что туда попало. Можно ваще циклом с клиента... ну вот как сказать "оптимальнее"? "для чего" - почему пропущено?
...
Рейтинг: 0 / 0
09.10.2013, 06:08:31
    #38421027
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
ещё есть вариант с экзистом:
Код: sql
1.
2.
3.
4.
delete from X
where aa=0 and exists(select bb from X Y where Y.aa<>0 and Y.bb=X.bb)
or
bb='нету' and exists(select aa from X Y where Y.aa=X.aa and Y.bb<>'нету')
...
Рейтинг: 0 / 0
09.11.2013, 02:22:15
    #38458584
InterSky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
tanglir,

Спасибо за предложенный вариант, но отмечу два минуса:

1) При моей небольшой таблице (7500 записей) мой вариант выполняется за 0.13 секунды, а ваш вариант за 2.38 секунды (разумеется запускаю перед тестом RESET QUERY CACHE). Тоесть ваш вариант почти в 20 раз медленней. Очевидно что поскольку у вас строится декартовое множество (даже два), то по мере увеличения базы время выполнения будет расти в геометрической прогрессии :(

2) Незнаю как более старшие версии, но MySQL 5.5.8 заявила что не может читать и удалять из одной таблицы (и даже инкапсулировать блоки в select * from (...) T не получилось), в то время как если заменить delete на select * то всё работает.

Тоесть получается что я могу сделать выборку, но не могу удалить вашим способом, даже не учитывая что он в 20 раз медленней.
...
Рейтинг: 0 / 0
09.11.2013, 13:56:38
    #38458731
Cygapb-007
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
alter table X add key ab(aa,bb);
alter table X add key ba(bb,aa);

delete from X
where x.aa=0 and exists(
  select 1 from X e where e.bb=x.bb and e.aa<>x.aa
  );

delete from X
where x.bb='нету' and exists(
  select 1 from X e where e.aa=x.aa and e.bb<>x.bb
  );

P.S. Две операции DELETE работают быстрее, чем одна с OR
...
Рейтинг: 0 / 0
09.11.2013, 14:46:45
    #38458753
InterSky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
Cygapb-007,

Если не ошибаюсь, до версии 4.5 у MySQL действительно было невыгодно использовать OR, потому что MySQL использовала только один ключь (в данном случае или ab или ba), и для ускорения селектов приходилось использовать UNION. Но ситуация давно исправлена (наверно лет 5-8 назад).

В данном примере время исполнения обоих ваших запросов полностью совпадает с временем выполнения одного запроса с OR:
Код: sql
1.
2.
3.
4.
select * from X where 
(x.aa=0 and exists(select 1 from X e where e.bb=x.bb and e.aa<>x.aa))
OR
(x.bb='нету' and exists(select 1 from X e where e.aa=x.aa and e.bb<>x.bb));



Однако повторюсь о чём писал выше: MySQL не даёт возможность делать запрос и удаление из дной талицы!
Тоесть я не могу выполнить DELETE, я могу только сделать SELECT *

Выполняя ваш запрос я получаю:
SQL execute error # 1093. Response from database:
You can't specify target table 'X' for update in FROM clause

Может в эта проблема уже решена в последних версиях MySQL, но в 5.5.8 нельзя.
...
Рейтинг: 0 / 0
09.11.2013, 22:25:29
    #38459007
Cygapb-007
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?)
InterSky ,

Да, действительно ругается...

http://sqlfiddle.com/#!2/6f768/1
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Как оптимальней избавиться от дублей? (пример и решени, но может можно оптимальней?) / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]