Проблема 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
У вас есть три варианта:
Коррелированный подзапрос.
SELECT * FROM TableA, ГДЕ НЕ СУЩЕСТВУЕТ (SELECT * FROM TableB, ГДЕ TableB.ID = TableA.ID)
Некоррелированный подзапрос.
SELECT * FROM TableA, ГДЕ НЕ ИДЕТ (ВЫБЕРИТЕ ID ИЗ TableB)
НАРУЖНОЕ СОЕДИНЕНИЕ с исключением 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 для второй таблицы