Страница 1 из 1

MySQL вопрос

Добавлено: 27 авг 2009, 13:35
Stanislav
Есть такая задача:
1. таблица users: id, ....
2. таблица mail_lists: ..., user_id, ....
3. далеко не все юзеры принадлежат к какому-либо списку рассылки
Вопрос: как удалить лишних юзеров?

Re: MySQL вопрос

Добавлено: 27 авг 2009, 13:42
Дима
Что-нибудь типа такого ?
delete from users where not exists (select userId from mail_lists where userId = users.userId)

Re: MySQL вопрос

Добавлено: 27 авг 2009, 13:43
Yury
вообще-то говоря странная структура, по идее должны быть, типа, таблицы users, users_lists и lists, так как один пользователь может быть в разных листах, а в одном листе - разные пользователи, то двумя таблицами трудно обойтись

но если и в самом деле как ты написал, то где-то вот так:

DELETE * FROM users WHERE users.id NOT IN (SELECT user_id FROM mail_lists)

Re: MySQL вопрос

Добавлено: 27 авг 2009, 13:49
Дима
нашел пример: http://www.electrictoolbox.com/mysql-de ... n-another/
Надо же, даже с синтаксисом не напутал ;) По-моему, Юрин SQL тоже должен работать, если убрать * после DELETE ;)

Re: MySQL вопрос

Добавлено: 27 авг 2009, 13:58
Stanislav
А это нормально будет работать? количество строк в списках - 100000, количество юзеров - 500000.

Re: MySQL вопрос

Добавлено: 27 авг 2009, 14:01
Stanislav
Yury писал(а):вообще-то говоря странная структура, по идее должны быть, типа, таблицы users, users_lists и lists, так как один пользователь может быть в разных листах, а в одном листе - разные пользователи, то двумя таблицами трудно обойтись
но если и в самом деле как ты написал, то где-то вот так:
DELETE * FROM users WHERE users.id NOT IN (SELECT user_id FROM mail_lists)
Ну оно так и есть - просто я опустил несущественные для данной задачи поля и таблицы...

Re: MySQL вопрос

Добавлено: 27 авг 2009, 14:17
Yury
Stanislav писал(а):
Yury писал(а):вообще-то говоря странная структура, по идее должны быть, типа, таблицы users, users_lists и lists, так как один пользователь может быть в разных листах, а в одном листе - разные пользователи, то двумя таблицами трудно обойтись
но если и в самом деле как ты написал, то где-то вот так:
DELETE * FROM users WHERE users.id NOT IN (SELECT user_id FROM mail_lists)
Ну оно так и есть - просто я опустил несущественные для данной задачи поля и таблицы...
они существенны, строго говоря, так как если так и есть, то у тебя в таблице листов не будет user_id, а будет id из промежуточной таблицы

Re: MySQL вопрос

Добавлено: 27 авг 2009, 14:18
Yury
Дима писал(а):Юрин SQL тоже должен работать, если убрать * после DELETE ;)
бывает :oops:
я чаще селектами пробавляюсь

Re: MySQL вопрос

Добавлено: 27 авг 2009, 14:23
Stanislav
Yury писал(а):
Stanislav писал(а):
Yury писал(а):вообще-то говоря странная структура, по идее должны быть, типа, таблицы users, users_lists и lists, так как один пользователь может быть в разных листах, а в одном листе - разные пользователи, то двумя таблицами трудно обойтись
но если и в самом деле как ты написал, то где-то вот так:
DELETE * FROM users WHERE users.id NOT IN (SELECT user_id FROM mail_lists)
Ну оно так и есть - просто я опустил несущественные для данной задачи поля и таблицы...
они существенны, строго говоря, так как если так и есть, то у тебя в таблице листов не будет user_id, а будет id из промежуточной таблицы
Нет, я же написал как у меня :-)
users: id, name, email
lists: id, list_name
mail_lists: id, user_id, list_id, status

Re: MySQL вопрос

Добавлено: 27 авг 2009, 15:06
Kate
DELETE FROM users WHERE id NOT IN (SELECT userid FROM mail_lists)
можно даже DELETE FROM users WHERE id NOT IN (SELECT DISTINCT userid FROM mail_lists)

Re: MySQL вопрос

Добавлено: 28 авг 2009, 06:56
Stanislav
Отработало на удивление быстро - снесло 400000 записей меньше чем за минуту. Оно что индексирует результат подзапроса? Или пользуется существующим индексом?

Re: MySQL вопрос

Добавлено: 28 авг 2009, 07:16
Дима
И то, и другое. О том, как именно и что использовалсь, можно посмотреть в плане выполнения запроса: http://dev.mysql.com/doc/refman/5.0/en/ ... plain.html
Правда, насколько я вижу, EXPLAIN работает только для SELECT запросов, ну это не страшно - придется заменить DELETE на SELECT *

Re: MySQL вопрос

Добавлено: 28 авг 2009, 08:16
Yury
Stanislav писал(а):Нет, я же написал как у меня :-)
ясно.. название промежуточной таблицы сбило с толку

Re: MySQL вопрос

Добавлено: 28 авг 2009, 08:25
Stanislav
Yury писал(а):
Stanislav писал(а):Нет, я же написал как у меня :-)
ясно.. название промежуточной таблицы сбило с толку
Сам с толку сбитый неоднократно... Я пытаюсь пофиксить супер софт из России. При удалении списка рассылки, юзеры не удаляются, но и не могут быть показаны/удалены/прилеплены в другой список никакими ихними средствами :-) Приходится через СКЛ

Re: MySQL вопрос

Добавлено: 28 авг 2009, 09:04
Дима
Stanislav писал(а):При удалении списка рассылки, юзеры не удаляются, но и не могут быть показаны/удалены/прилеплены в другой список никакими ихними средствами :-) Приходится через СКЛ
А в MySQL уже есть триггеры ? :) Если да, то можно наваять триггер, который будет удалять юзера при удалении последнего листа рассылки, в котором он участвует. Впрочем, это и называется "через задницу". Лучше, конечно, поправить кривой код, который создает рассылку ;)