Напротив внутреннего соединения - PullRequest
17 голосов
/ 06 августа 2010

Что будет противоположностью внутреннего соединения?Для таблицы таблицы Person (int PersonId, varchar PersoName, int AddrId) я хочу знать строки в Person с bad AddrId, у которых нет строки в таблице Address.

Ответы [ 4 ]

57 голосов
/ 06 августа 2010

Что будет противоположностью внутреннего соединения?

НАРУЖНОЕ соединение, которое может иметь три варианта:

  • ЛЕВЫЙ
  • RIGHT
  • ПОЛНЫЙ

Это хорошее визуальное представление JOIN

Я хочу знать строки в Person с неверным AddrId, у которых нет строки в таблице адресов.

Использование LEFT JOIN / IS NULL

   SELECT p.*
     FROM PERSON p
LEFT JOIN ADDRESS a ON a.addrid = p.addrid
    WHERE a.addrid IS NULL

Использование NOT EXISTS

SELECT p.*
  FROM PERSON p
 WHERE NOT EXISTS(SELECT NULL
                    FROM ADDRESS a
                   WHERE a.addrid = p.addrid)

Использование NOT IN

SELECT p.*
  FROM PERSON p
 WHERE p.addrid NOT IN (SELECT a.addrid
                          FROM ADDRESS a)
7 голосов
/ 06 августа 2010

Внутреннее соединение не является диаметральным по отношению к внешнему соединению.Они служат разным целям.Однако общий шаблон для поиска строк из одной таблицы, которые не существуют в другой, заключается в использовании внешнего соединения:

Select ...
From Table1
    Left Join Table2
        On Table2.ForeignKeyCol = Table1.PrimaryKeyCol
Where Table2.PrimaryKeyCol Is Null

. Это возвращает все строки из таблицы Table1 и любые соответствующие строки из таблицы Table2, так что если данныйСтрока Table1 не имеет соответствия Table2, возвращается ноль для столбцов Table2.Затем, потребовав, чтобы столбец, не имеющий значения NULL, (Table2.PrimaryKeyCol) имел значение Null, я получу все строки из Table1, которые не существуют в Table2.Используя имена таблиц вашего примера, мы получили бы что-то вроде:

Select ...
From Person
    Left Join Address
        On Address.PersonId = Person.Id
Where Address.Id Is Null
5 голосов
/ 06 августа 2010

Если вы рассматриваете внутреннее объединение как строки двух таблиц, которые удовлетворяют определенному условию, тогда противоположными будут строки в или таблице, которые этого не делают.

Например, следующее выберет всех людей с адресами в таблице адресов:

SELECT p.PersonName, a.Address
FROM people p
JOIN addresses a
    ON p.addressId = a.addressId

Я полагаю, что "противоположным" этому было бы выбрать всех людей без адресов и все адреса без людей. Однако, похоже, это не то, о чем вы спрашиваете, вам, кажется, интересен только один компонент этого: все люди без адреса в таблице адресов.

Для этого лучше всего использовать левое соединение:

SELECT p.PersonName
FROM people p
LEFT JOIN addresses a
   ON p.addressId = a.addressId
WHERE a.addressId IS NULL

Обратите внимание, что часто некоторые предпочитают писать это по-другому, поскольку, по их мнению, они более читабельны (однако по моему опыту с большими таблицами это работает хуже, чем описанным выше способом):

SELECT PersonName
FROM people
WHERE addressId NOT IN (SELECT addressId FROM addresses)
0 голосов
/ 06 августа 2010

Я думаю, что лучшим решением было бы использование EXISTS. Как это:

SELECT * FROM Person P
WHERE P.AddrId IS NOT NULL 
  AND NOT EXISTS ( SELECT 1 FROM Address A WHERE A.AddrId = P.AddrId )

Приведенный выше запрос вернет каждого человека, у которого установлен AddrId, но у которого нет соответствующей записи в таблице адресов.

Obs.: Используйте константу 1 в запросе EXISTS, чтобы избежать доступа к таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...