Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > исключающая выборка


Автор: Artemon 6.4.2010, 08:16
Есть 2 таблицы, в которых присутствует связующее поле.

Вот таким запросом я выбираю записи из первой таблицы и сопостовляю данные из 2-й таблицы.

Код

SELECT * FROM ce129
LEFT JOIN deletedobjects ON ce129.id = deletedobjects.id_object


Как сделать, чтобы из первой таблиы выбирались ТОЛКО данные, которым нет соответствия во-второй таблице ?

Автор: azesmcar 6.4.2010, 08:34
NOT IN?
Код

SELECT * FROM ce129 WHERE id NOT IN (SELECT id FROM deletedobjects)


еще вариант - OUTER JOIN ... WHERE FIELD IS NULL
еще вариант - MINUS (но его кажется нет в MySQL)

но по моему это извращения..не лучше хранить статус в таблице is_deleted?

Автор: Zloxa 6.4.2010, 08:34
Цитата(Artemon @  6.4.2010,  08:16 Найти цитируемый пост)

Как сделать, чтобы из первой таблиы выбирались ТОЛКО данные, которым нет соответствия во-второй таблице ?

Код

SELECT * FROM ce129
LEFT JOIN deletedobjects ON ce129.id = deletedobjects.id_object
where deletedobjects.id_object is null

 smile

Добавлено через 2 минуты и 21 секунду
Цитата(azesmcar @  6.4.2010,  08:34 Найти цитируемый пост)
еще вариант

еще вариант - коррелированный not exists smile
Код

SELECT * FROM ce129
LEFT JOIN ce129
where not exists (select null from deletedobjects where ce129.id = deletedobjects.id_object)

Автор: azesmcar 6.4.2010, 08:37
Zloxa

я чего-то не понял или там должен быть LEFT OUTER JOIN?

Добавлено через 1 минуту и 50 секунд
Цитата(Zloxa @  6.4.2010,  08:34 Найти цитируемый пост)
еще вариант - коррелированный not exists smile

только что проверил, один фиг, все работает одинаково медленно smile

Автор: Artemon 6.4.2010, 08:41
Спасибо, оба варианта рабочие.

Сбило с толку, что 

"is null" != "= null"

Автор: Akina 6.4.2010, 08:45
Цитата(azesmcar @  6.4.2010,  09:37 Найти цитируемый пост)
я чего-то не понял или там должен быть LEFT OUTER JOIN?

Нет, у Zloxa для MySQL (и подавляющего имхо большинства иных СУБД) всё правильно. Причём при индексах по ce129.id и deletedobjects.id_object соответственно - должно просто летать, в отличие от NOT IN / NOT EXIST, где подзапрос == временная таблица.

Автор: azesmcar 6.4.2010, 09:01
Akina

только что запустил оба варианта

вариант с LEFT JOIN
user posted image

вариант с NOT IN
user posted image

поля индексированы.

и я не совсем понимаю какая разница..что LEFT JOIN, что LEFT OUTER JOIN..это же одна фигня (или я ошибаюсь?).

Автор: Akina 6.4.2010, 09:57
Цитата(azesmcar @  6.4.2010,  10:01 Найти цитируемый пост)
только что запустил оба варианта

А explain запросов не покажешь?

Автор: azesmcar 6.4.2010, 10:04
Akina
Да, сейчас..

Код

explain select * from records where customer_id not in (select id from customers)

Цитата

1    PRIMARY    records    ALL     4969785    Using where
2    DEPENDENT SUBQUERY    customers    unique_subquery    PRIMARY    PRIMARY    4    func    1    Using index


Код

explain select * from records c left join customers cs on cs.id = c.customer_id where cs.id is null

Цитата

1    SIMPLE    c    ALL     4969785    
1    SIMPLE    cs    eq_ref    PRIMARY    PRIMARY    4    mydb.c.customer_id    1    Using where; Not exists


Автор: Zloxa 6.4.2010, 10:18
Цитата(azesmcar @  6.4.2010,  09:01 Найти цитируемый пост)
что LEFT JOIN, что LEFT OUTER JOIN..это же одна фигня

Да, хотя явного доказательства тому, что слово outer может быть опущено без изменения смысла фразы, в документации по MySql я не нашел. Видимо составители документации считали это столь очевидным, что им в голову не пришло, что могут быть пытливые умы, которые зададутся таким вопросом.

Цитата(azesmcar @  6.4.2010,  10:04 Найти цитируемый пост)
Using where; Not exists

 smile 

Автор: azesmcar 6.4.2010, 10:19
Цитата(Zloxa @  6.4.2010,  10:18 Найти цитируемый пост)
Да, хотя явного доказательства тому, что слово outer может быть опущено без изменения смысла фразы, в документации по MySql я не нашел. Видимо составители документации считали это столь очевидным, что им в голову не пришло, что могут быть пытливые умы, которые зададутся таким вопросом.

Ага smile я потом допер что это одно и тоже, но сперва безрезультатно прочесал документацию. Не знал о такой форме записи.


Цитата(Zloxa @  6.4.2010,  10:18 Найти цитируемый пост)

Цитата(azesmcar @  6.4.2010,  10:04 Найти цитируемый пост)
Using where; Not exists

 smile  

интересно не правда ли smile

Автор: Zloxa 6.4.2010, 11:04
на самом деле реализации через not in, not exists, outer join - в общем случае должны давать разные результаты. outer join будет "размножать исходный" набор, но не в нашем случае, т.к. отношение у нас многие к одному, объединение у нас происходит по pk, в нашем случае left join и not exists взаимозаменяемы. Not in и not exists дадут разные результаты если фильтруемое поле может принимать значение null. Не мог бы ты показать каков будет  план, если накинуть на records.customer_id ограничение not null?

Добавлено через 2 минуты и 44 секунды
зы под "нашим случаем" в последнем посте я подразумеваю случай, показанный azesmcar. У ТС, Судя по всему иной случай. Думается мне что у него критериями объединения вступают pk потому все три варианта эквивалентны.

Автор: azesmcar 6.4.2010, 11:17
Цитата(Zloxa @  6.4.2010,  11:04 Найти цитируемый пост)
Не мог бы ты показать каков будет  план, если накинуть на records.customer_id ограничение not null?

уже стоит.

Цитата(Zloxa @  6.4.2010,  11:04 Найти цитируемый пост)
зы под "нашим случаем" в последнем посте я подразумеваю случай, показанный azesmcar. У ТС, Судя по всему иной случай. Думается мне что у него критериями объединения вступают pk потому все три варианта эквивалентны. 

повторю свой вопрос, в случае ТС я не вижу причин использования отдельной таблицы, почему бы не использовать просто boolean флаг is_deleted? Это будет намного быстрее.

Добавлено @ 11:23
оп...я дико извиняюсь...у меня с таблицы куда то индекс пропал smile 

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

Автор: azesmcar 6.4.2010, 12:53
сделал, проверил - картина не изменилась. Резульаты те же самые.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)