2013-06-07 3 views
3

У меня есть две таблицы в моей базе данных:Выбрать записи из таблицы, которые не находятся в другой таблице

Таблица 1 (BonInterne):

+---------+ 
| num | 
+---------+ 
|1  | 
+---------+ 
|2  | 
+---------+ 
|3  | 
+---------+ 
|4  | 
+---------+ 

Таблица 2 (LigneBonInterne):

+---------+-----------+ 
|numOrdre |numBon  | 
+---------+-----------+ 
|20  |1   + 
+---------+-----------+ 
|21  |2   | 
+---------+-----------+ 
|22  |NULL  + 
+---------+-----------+ 
|23  |2   | 
+---------+-----------+ 
|24  |1   + 
+---------+-----------+ 
|25  |2   | 
+---------+-----------+ 
|26  |NULL  + 
+---------+-----------+ 
|27  |1   | 
+---------+-----------+ 

Я хочу получить все записи из таблицы 1, которые имеют номер не во второй таблице, и это сценарий, который я пробовал:

Но MySQL вернул пустой набор результатов.

Он должен вернуться следующим образом:

+---------+ 
| num | 
+---------+ 
|3  | 
+---------+ 
|4  | 
+---------+ 

Что я должен изменить в своем запросе, чтобы получить эту таблицу ??

+3

Я просто проверял свой запрос, и он работает - http://www.sqlfiddle.com/#!2/c8bdf0/1 – Taryn

+0

@bluefeet в моей реальной базе данных есть значения NULL в столбце 'numBon'. Я думал, что не важно включать значения NULL в мой пример, см. изменения, которые я сделал. –

+1

Это меняет вещи, это детали, которые очень важны для ответа. – Taryn

ответ

2
Select B.num 
From BonInterne As B 
    Left Join LigneBonInterne As L 
     On L.numBon = B.num 
Where L.numBon Is Null 

SQL Fiddle version

Visual Explanation of Joins

Одно из объяснений, почему ваш исходный запрос не работают, если LigneBonInterne таблица содержит нулевые значения для numBon столбца. Функция In преобразуется в ряд операторов Or (например, Foo In(A,B,C) соответствует Foo = A Or Foo = B Or Foo = C. В случае Foo Not In(A,B,C) мы получаем Foo <> A And Foo <> B And Foo <> C.). Таким образом, если одно из значений равно null, мы получим сравнение с нулем и вернем false (технически оно возвращает Unknown).

Этот SQL Fiddle example показывает ваш первоначальный запрос, но обратите внимание, что я добавил значение null для numBon и не получаю результатов. Возьмите это значение, и мы это сделаем.

Если у вас есть нули в LigneBonInterne, то вышеуказанное решение будет работать. Другой вариант заключается в использовании функции In но отфильтровать аннулирует в вашем подзапрос

Select B.num 
From BonInterne As B 
Where Not In (
       Select L1.numBon 
       From LigneBonInterne As L1 
       Where L1.numBon Is Not Null 
       ) 

Другой вариант заключается в использовании Exists вместо In:

Select B.num 
From BonInterne As B 
Where Not Exists (
        Select 1 
        From LigneBonInterne As L1 
        Where L1.numBon = B.num 
        ) 

При использовании Exists, положение Select полностью игнорируется. Некоторые люди используют Select *, некоторые используют Select Null, некоторые используют Select 1. Это не имеет значения; все, что имеет значение, заключается в том, возвращает ли остальная часть запросов строки или нет. Этот тип запроса называется коррелированным подзапросом, потому что во внутреннем запросе есть ссылка на внешний запрос (L1.numBon = B.num).

Итак, в какой форме вы должны использовать? В этом случае ясность намерения может быть достигнута любой из трех форм. Однако продукты базы данных отличаются своей способностью эффективно обрабатывать коррелированные подзапросы. В случае с MySQL он, вероятно, будет работать лучше всего с помощью Left Join, затем функции In и последней функции Exists.

+0

Да, вы правы, 'LigneBonInterne' содержит значения NULL в столбце' numBon', как я могу получить результат, который я хочу, даже если есть значение NULL? –

+0

@ user2417302 - У вас есть несколько вариантов, которые я обновлю для публикации. – Thomas

+0

Выберите столбец, который не имеет значения NULL? – Strawberry

2

SQL 101

SELECT x.* 
    FROM x 
    LEFT 
    JOIN y 
    ON y.thing = x.thing 
WHERE y.thing IS NULL; 
2

Ваш запрос очень близко, нужно просто включить ИНЕКЕ для фильтрации для тех значений, которые не являются нуль:

SELECT num 
FROM BonInterne 
WHERE num NOT IN (SELECT numBon 
        FROM LigneBonInterne 
        where numBon is not null); 

См SQL Fiddle with Demo

Смежные вопросы