SQL: можно ли переписать любой тип объединения как набор условий WHERE? - PullRequest
1 голос
/ 09 ноября 2010

Пример:

Если у меня есть таблица вещей и их владельцев.

Я могу сделать либо, либо получить тот же результат для естественного соединения:

SELECT * FROM owners, things WHERE owners.id = things.owner_id
SELECT * FROM owners JOIN things ON owners.id = things.owner_id

Теперь, если я хочу сделать левое соединение? Вот так, куда возвращаются все владельцы ...

SELECT * FROM owners LEFT JOIN things ON owners.id = things.owner_id

Возможно ли переписать любое соединение как набор условий WHERE?

Спасибо

Ответы [ 4 ]

6 голосов
/ 09 ноября 2010

INNER JOIN всегда можно переписать как неявное соединение.

OUTER JOIN иногда может быть переписан с помощью строки проприетарных предложений (+) в Oracle, * в SQL Server и т. Д., Но не всегда.

Кроме того, OUTER JOIN можно переписать с помощью UNION ALL и подзапросов:

SELECT  *
FROM    a
FULL JOIN
        b
ON      some_condition(a, b)

совпадает с

SELECT  *
FROM    a, b
WHERE   some_condition(a, b)
UNION ALL
SELECT  a.*, NULL, NULL, …, NULL
FROM    a
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    b
        WHERE   some_condition(a, b)
        )
UNION ALL
SELECT  NULL, NULL, …, NULL, b.*
FROM    b
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    a
        WHERE   some_condition(a, b)
        )

Раньше это был обходной путь для Oracle и PostgreSQL, который не поддерживал синтаксис ANSI в более ранних версиях, а также обходной путь для MySQL, который не поддерживает FULL JOIN

Вы должны использовать синтаксис ANSI OUTER JOIN, если ваша база данных поддерживает его.

2 голосов
/ 09 ноября 2010

Зависит от того, какая база данных и поддерживается ли их устаревший синтаксис внешнего соединения.Критерии JOINs в предложении WHERE - это синтаксис ANSI-89, но, как вы заметили, поддержка OUTER join отсутствует, поэтому поставщики реализовали свой собственный.

Oracle:

SELECT * 
  FROM owners, things 
 WHERE owners.id = things.owner_id(+)

SQLСервер:

SELECT * 
  FROM owners, things 
 WHERE owners.id =* things.owner_id

Рекомендация

Не - используйте синтаксис ANSI-92.Он переносим, ​​и на горизонте нет синтаксиса для его замены:

   SELECT * 
     FROM owners o
LEFT JOIN things t ON o.id = t.owner_id
1 голос
/ 09 ноября 2010

Конечно, вы не захотите использовать неявный синтаксис когда-либо (это очень плохая методика программирования, которая подвержена ошибкам и создает проблемы с обслуживанием), так почему вы хотите писать левые соединения таким образом?

Я не могу говорить за все базы данных, но неявный синтаксис левого соединения в SQL Server устарел и не должен использоваться ни при каких обстоятельствах, поскольку он не гарантирует правильных результатов. У меня возникли проблемы с результатами, если вы объединили явный синтаксис соединения для левых соединений с неявным синтаксисом соединения, поэтому, если вам нужно левое соединение, исправьте все соединения, чтобы они были явными.

1 голос
/ 09 ноября 2010

Что касается вашего примера LEFT JOIN, то вы можете выразить это в предложении WHERE, в зависимости от разновидности и версии SQL.

Несколько условий для одного JOIN не могут быть выражены в предложении WHERE в определенных случаях при использовании LEFT JOIN (и некоторых других объединений).

В общем, использование синтаксиса соединения ANSI в отличие от синтаксиса Theta ("WHERE clause") обычно считается наилучшей практикой.

...