2010-02-11 5 views
8

У меня возникла проблема с поиском запроса, который, как я думаю, должен работать. Это в формеmysql SELECT NOT IN() - непересекающийся набор?

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

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

ответ

12

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

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, будут сообщать о ложных срабатываниях.

+0

Знаешь что? Я выполнил этот запрос, и это заняло много времени (более 10 минут), поэтому я его убил. Затем я настраиваю временные таблицы для двух таблиц и вставлял различную информацию. Затем я выполнил запрос к временным таблицам. Взял одну минуту и ​​4 секунды. Почему mysql не мог оптимизировать этот запрос? – user151841

+1

Если честно, mysql довольно глупо и медленно в некоторых отношениях. Oracle, MS SQL и PostgreSQL во многих отношениях делают намного лучше. Конечно, это также будет намного быстрее, если вы добавите индексы в столбцы таблиц, если у вас их уже нет. хотя это будет стоить времени на вставку, так как индексы должны обновляться каждый раз, это вопрос того, сколько раз вы выполняете каждую операцию и что является более критичным для времени. – wich

0

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

(Edit :) Попробуйте с помощью 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, как это упоминает Чарльз ниже.

+0

Святой Боже, что бы сделать запрос кошмар. Меня интересуют только значения a, b или c в зависимости от значений двух других! – user151841

+0

Как насчет использования соединения? Внутреннее присоединение ко всем 3 полям должно возвращать все нечеткие кортежи – froadie

+0

Или как насчет использования существует? SELECT a, b, c FROM t1 НЕ СУЩЕСТВУЕТ (SELECT * FROM t2 WHERE t1.a = t2.a И t1.b = t2.b И t1.c = t2.c). Не уверен, что это точно правильно, у меня не было большого опыта с существующим – froadie

0

SELECT DISTINCT t1. * FROM t1 LEFT JOIN t2 ON (T1.a = T2.a И T1.b = t2.b И t1.c = t2.c) где T2.a IS NULL

+0

Это очень плохая идея, если таблицы большие, что левое соединение будет болезненно медленным. Вы много работаете, читаете обе таблицы, полностью создавая набор результатов левого соединения и т. Д., Что просто не нужно. – wich

+0

Действительно. Неэффективность. – Charles

-1

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

Я проверил это с аналогичным столом и работает.

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

Использование MySQL world дб:

-- 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

Было бы лучше использовать NOT EXISTS, а не IN, что приведет к созданию результирующего набора для вспомогательного запроса, прочитав всю таблицу, когда вы используете NOT EXISTS, для вспомогательного запроса не нужно создавать набор результатов, и если столбцы индексируются, NOT EXISTS будут читать только индексы. – wich

+0

Вы в этом уверены? Если столбцы не индексируются, NOT EXISTS - это медленный NOT IN. – Yada

0

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

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

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

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

+1

В зависимости от определения столбцов a, b и c из t2 это может быть неверно! Если они допускают значения NULL, тогда результат для NOT IN всегда будет неизвестен для любого такого значения. NOT EXISTS * - это правильный способ выразить это, НЕ СУЩЕСТВУЕТСЯ для этого. – wich

+0

Удивительный! Благодарю. – user151841

3

У меня возникли проблемы с поиском правильного пути выполнения этого запроса, даже с предоставленными ответами; Затем я нашел документации ссылку 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