Проблема SQL-соединения

Я хочу получить все записи из одной таблицы, когда во второй таблице нет совпадений.

Так что это как бы противоположность внутреннего соединения.

8 ответов

Решение

Вам нужен запрос LEFT JOIN WHERE IS NULL (он же внешнее соединение):

SELECT table1.*
FROM table1
LEFT OUTER JOIN table2 
   ON table1.id = table2.id
WHERE table2.id IS NULL

Или НЕ В:

SELECT *
FROM table1
WHERE id NOT IN (SELECT id FROM table2)

Это внешнее соединение:

SELECT *
  FROM tableA AS a
  LEFT JOIN tableB AS b USING(x)

Скажем, у вас есть:

TABLEA:

a | x
-----
1 | 1
3 | 3

таблица B:

b | x
-------
1 | 'a'
2 | 'b'

тогда запрос выше даст вам

a |  b   | x
------------
1 |  'a' | 1
3 | NULL | 3

если ты хочешь

a    |  b   | x
----------------
1    | 'a'  | 1
NULL | 'b'  | 2
3    | NULL | 3

ты должен использовать FULL OUTER JOIN вместо LEFT JOIN,

РЕДАКТИРОВАТЬ: Как Ларри Lustig сказал мне (и я думаю, что правильно после перечитывания вопроса) OP не хочет никаких строк из B. Таким образом, запрос должен быть:

SELECT a.*
  FROM tableA AS a
  LEFT JOIN tableB AS b USING(x)
 WHERE b.x IS NULL

это даст

 a | x 
-------
 3 | 3

У вас есть три варианта:

  1. Коррелированный подзапрос.

    SELECT * FROM TableA, ГДЕ НЕ СУЩЕСТВУЕТ (SELECT * FROM TableB, ГДЕ TableB.ID = TableA.ID)

  2. Некоррелированный подзапрос.

    SELECT * FROM TableA, ГДЕ НЕ ИДЕТ (ВЫБЕРИТЕ ID ИЗ TableB)

  3. НАРУЖНОЕ СОЕДИНЕНИЕ с исключением NULL.

    SELECT * FROM TableA LEFT [OUTER] JOIN TableB ON TableA.ID = TableB.ID ГДЕ TableB.ItsPrimaryKey НЕ ПУСТО

В последнем примере некоторые СУБД требуют слово OUTER, некоторые разрешают его, а некоторые вообще не допускают.

В зависимости от СУБД различные варианты могут давать разные планы выполнения и разную производительность. Выберите тот, который обладает хорошими характеристиками и лучше всего отражает ваши намерения.

Внешнее соединение. Технически возможно ПОЛНОЕ НАРУШЕНИЕ;)

"Противоположность" внутреннего соединения называется внешним соединением.

Добавление к решению Йоханнеса Вейса решения другого вопроса о поиске объектов в таблице a без объектов в таблице b:

SELECT *
FROM tableA AS a
LEFT JOIN tableB AS b
USING(x)
WHERE b.foo IS NULL

Вы ищете LEFT JOIN или FULL OUTER JOIN. Не все СУБД поддерживают FULL.

Это возможно с помощью UNION, например, в MySQL:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

Я считаю, что вы ищете FULL OUTER JOIN (работает с Oracle 9i+).

РЕДАКТИРОВАТЬ: плохо прочитал ваш вопрос... СЛЕВАЙТЕ ПРИСОЕДИНЯЙТЕСЬ, если вы хотите только значения NULL для второй таблицы

Другие вопросы по тегам