mysql SELECT NOT IN () - непересекающийся набор? - PullRequest
10 голосов
/ 11 февраля 2010

У меня проблема с получением запроса на работу, который, я думаю, должен работать. Это в форме

SELECT DISTINCT a, b, c FROM t1 WHERE NOT IN ( SELECT DISTINCT a,b,c FROM t2 ) AS alias

Но mysql дросселирует, где начинается "IN (". Поддерживает ли mysql этот синтаксис? Если нет, как я могу получить эти результаты? Я хочу найти в таблице 1 различные наборы (a, b, c) не существует в таблице 2.

Ответы [ 6 ]

13 голосов
/ 11 февраля 2010

Вы должны использовать не существует:

SELECT DISTINCT a, b, c FROM t1 WHERE NOT EXISTS (SELECT NULL FROM t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c)

Использование NOT IN - не лучший способ сделать это, даже если вы проверите только один ключ. Причина в том, что если вы используете NOT EXISTS, СУБД должна будет проверять индексы, только если индексы существуют для нужных столбцов, тогда как для NOT IN она должна будет считывать фактические данные и создавать полный набор результатов, который впоследствии необходимо проверить. .

Использование LEFT JOIN с последующей проверкой NULL также является плохой идеей, так как большие таблицы будут мучительно медленными, поскольку в запросе необходимо выполнить полное соединение, полностью прочитав обе таблицы и впоследствии отбросив большую их часть. , Кроме того, если столбцы допускают значения NULL, проверка на NULL сообщит о ложных срабатываниях.

4 голосов
/ 27 июля 2012

У меня были проблемы с поиском правильного способа выполнения этого запроса, даже с предоставленными ответами; затем я нашел нужную справочную документацию по MySQL:

SELECT DISTINCT store_type
FROM stores 
WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);

Хитрость, которую мне пришлось обернуть, заключалась в использовании ссылки на таблицу «магазины» из первого запроса внутри подзапроса. Надеюсь, что это помогает (или помогает другим, поскольку это старая ветка.)

С http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html

0 голосов
/ 12 февраля 2010

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

Вот правильный синтаксис того, что я пытался сделать.

SELECT DISTINCT a, b, c FROM t1 WHERE (a,b,c) NOT IN ( SELECT DISTINCT a,b,c FROM t2 )

Не могу поручиться за его эффективность, но я неявно задавал более широкие вопросы: «Как выразить эту мысль в SQL», а не «Как получить конкретный набор результатов». Я знаю, что это несправедливо по отношению ко всем, кто сделал удар, извини!

0 голосов
/ 11 февраля 2010

Необходимо добавить список столбцов после предложения WHERE и УДАЛИТЬ псевдоним.

Я проверил это с похожей таблицей, и она работает.

SELECT DISTINCT a, b, c 
FROM t1 WHERE (a,b,c)
NOT IN (SELECT DISTINCT a,b,c FROM t2)

Использование mysql world db:

-- dont include city 1, 2
SELECT DISTINCT id, name FROM city 
WHERE (id, name) 
NOT IN (SELECT id, name FROM city  WHERE ID IN (1,2))
0 голосов
/ 11 февраля 2010

ВЫБЕРИТЕ ЗНАЧЕНИЕ t1. * ОТ t1 ВЛЕВО СОЕДИНЯЕТСЯ t2 ВКЛ (t1.a = t2.a И t1.b = t2.b И t1.c = t2.c) ГДЕ t2.a НЕДЕЙСТВИТЕЛЬНО

0 голосов
/ 11 февраля 2010

Насколько я знаю, NOT IN можно использовать только для 1 поля за раз.И поле должно быть указано между "WHERE" и "NOT IN".

(Правка :) Попробуйте использовать NOT EXISTS:

SELECT a, b, c 
FROM t1 
WHERE NOT EXISTS 
   (SELECT * 
   FROM t2 
   WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c)

Кроме того, внутреннее соединение наЕсли a, b и c равны, это даст вам все кортежи, отличные от DISTINCT, тогда как LEFT JOIN с предложением WHERE IS NULL должны дать вам DISTINCT, как упоминал Чарльз ниже.

...