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

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

2 голосов
/ 11 марта 2010

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

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

Ответы [ 8 ]

4 голосов
/ 11 марта 2010

Вам необходим ЛЕВОЕ СОЕДИНЕНИЕ, ГДЕ НУЛЬ запрос (иначе внешнее объединение):

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)
1 голос
/ 11 марта 2010

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

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

    ВЫБРАТЬ * ИЗ СТОРОНЫ А ГДЕ НЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ИЗ таблицы B, ГДЕ TableB.ID = TableA.ID)

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

    ВЫБРАТЬ * ИЗ СТОРОНЫ А ГДЕ ID НЕ ВХОДИТ (ВЫБЕРИТЕ ID ИЗ TableB)

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

    ВЫБРАТЬ * ИЗ СТОРОНЫ А ЛЕВЫЙ [НАРУЖНЫЙ] РЕЙТИНГ TableB ON TableA.ID = TableB.ID ГДЕ TableB.ItsPrimaryKey НЕ НУЛЬ

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

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

1 голос
/ 11 марта 2010

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

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

Допустим, у вас есть:

таблица A:

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.

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

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

, который даст

 a | x 
-------
 3 | 3
0 голосов
/ 11 марта 2010

Вы ищете левое соединение или полное внешнее соединение Однако не все СУБД поддерживают 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
0 голосов
/ 11 марта 2010

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

SELECT *
FROM tableA AS a
LEFT JOIN tableB AS b
USING(x)
WHERE b.foo IS NULL
0 голосов
/ 11 марта 2010

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

0 голосов
/ 11 марта 2010

Я полагаю, что вы ищете ПОЛНОЕ НАРУЖНОЕ СОЕДИНЕНИЕ (работает с Oracle 9i +).

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

0 голосов
/ 11 марта 2010

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

...