Напротив внутреннего соединения
Что будет противоположностью внутреннего соединения? Для таблицы Table Person (int PersonId, varchar PersoName, int AddrId)
, я хочу знать строки в Person с плохим AddrId
, которые не имеют строки в таблице Address
.
Ответы
Ответ 1
Что будет противоположностью внутреннего соединения?
Соединение OUTER, которое может быть трех вариантов:
Это хорошее визуальное представление JOINs
Я хочу знать строки в Person with bad AddrId, которые не имеют строки в таблице Address.
Использование 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)
Ответ 2
Внутреннее соединение не является диаметрическим для Outer Join. Они служат различным целям. Однако общий шаблон для поиска строк из одной таблицы, которых нет в другом, заключается в использовании Outer Join:
Select ...
From Table1
Left Join Table2
On Table2.ForeignKeyCol = Table1.PrimaryKeyCol
Where Table2.PrimaryKeyCol Is Null
Это возвращает все строки из Таблицы 1 и любые соответствующие строки из Таблицы 2, так что если в заданной таблице Table1 нет соответствия Table2, возвращается нуль для столбцов Table2. К тому времени, требуя, чтобы столбец с непустым значением (Table2.PrimaryKeyCol) был Null, я получу все строки из таблицы 1, которых нет в таблице2. Используя ваши имена таблиц в таблице, у нас будет что-то вроде:
Select ...
From Person
Left Join Address
On Address.PersonId = Person.Id
Where Address.Id Is Null
Ответ 3
Если вы считаете внутреннее соединение как строки из двух таблиц, удовлетворяющих определенному условию, то противоположными будут строки в любой таблице, которые этого не делают.
Например, следующее будет выбирать всех людей с адресами в таблице адресов:
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)
Ответ 4
Я думаю, что лучшим решением будет использование EXISTS. Вот так:
SELECT * FROM Person P
WHERE P.AddrId NOT NULL И НЕ СУЩЕСТВУЕТ (SELECT 1 FROM Address A WHERE A.AddrId = P.AddrId)
В приведенном выше запросе будет указан каждый человек, который установлен в AddrId, но не имеет соответствующей записи в таблице Address.
Обь.: Используйте константу 1 в запросе EXISTS, чтобы избежать доступа к таблице.