Запросы, которые неявные объединения SQL не могут сделать?

Я никогда не изучал, как работают объединения, но только с помощью select и предложения where было достаточно для всех запросов, которые я сделал. Есть ли случаи, когда я не могу получить правильные результаты, используя предложение WHERE, и мне приходится использовать JOIN? Если да, может кто-нибудь привести примеры? Благодарю.

7 ответов

Неявные объединения устарели более чем на 20 лет. Почему бы вам даже подумать о написании кода с ними?

Да, они могут создавать проблемы, которых нет в явных объединениях. Говоря о SQL Server, неявные синтаксисы левого и правого соединения не гарантируют правильные результаты. Иногда они возвращают перекрестное соединение вместо внешнего соединения. Это плохо. Это было верно даже по крайней мере до SQL Server 2000, и они постепенно сокращаются, поэтому их использование - это плохая практика.

Другая проблема с неявными объединениями состоит в том, что можно легко выполнить перекрестное объединение, забыв об одном из условий where, особенно когда вы объединяете слишком много таблиц. Используя явные объединения, вы получите синтаксическую ошибку, если вы забудете ввести условие соединения, и перекрестное соединение должно быть явно указано как таковое. Опять же, это приводит к запросам, которые возвращают неправильные значения или фиксируются с использованием различных, чтобы избавиться от перекрестного соединения, которое в лучшем случае неэффективно.

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

Я считаю, что некоторые ORM также требуют явных объединений.

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

Если вы пишете SQL-код любого вида, нет оправдания тому, что вы не понимаете объединения.

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

Есть ли случаи, когда я не могу получить правильные результаты, используя предложение WHERE, и мне приходится использовать JOIN?

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

Если критерии объединения находятся в WHERE затем используется синтаксис ANSI-89 JOIN. Причина для более нового синтаксиса JOIN в формате ANSI-92 заключается в том, что он сделал LEFT JOIN более согласованным в различных базах данных. Например, Oracle использовал (+) на стороне, которая была необязательной в то время как в SQL Server вы должны были использовать =*,

Синтаксис неявного объединения по умолчанию использует внутренние объединения. Иногда можно изменить неявный синтаксис объединения, чтобы указать внешние объединения, но в моем опыте это зависит от поставщика (я знаю, что у oracle есть нотация (-) и (+), и я считаю, что sqlserver использует *=). Итак, я считаю, что ваш вопрос можно свести к пониманию различий между внутренним и внешним объединением.

Мы можем посмотреть на простой пример для внутреннего и внешнего объединения, используя простой запрос..........

Неявное ВНУТРЕННЕЕ присоединение:

select a.*, b.*
from table a, table b
where a.id = b.id;

Приведенный выше запрос вернет ТОЛЬКО строки, в которых строка "a" имеет соответствующую строку в "b" для своего поля "id".

Явное ВНЕШНЕЕ СОЕДИНЕНИЕ:

select * from
table a LEFT OUTER JOIN table b
on a.id = b.id;

Приведенный выше запрос вернет КАЖДУЮ строку в a, независимо от того, есть ли у нее соответствующая строка в "b". Если для 'b' не найдено совпадений, поля 'b' будут нулевыми.

В этом случае, если вы хотите вернуть КАЖДУЮ строку в "a" независимо от того, имеет ли она соответствующую строку "b", вам нужно будет использовать внешнее соединение.

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

Oracle поддерживает LEFT JOIN и RIGHT JOIN используя их специальный оператор соединения (+) (и SQL Server, используемый для поддержки *= и =*на предикатах соединения, но больше не делает). Но простой FULL JOIN не может быть выполнено только с неявными соединениями:

      SELECT f.title, a.first_name, a.last_name
FROM film f
FULL JOIN film_actor fa ON f.film_id = fa.film_id
FULL JOIN actor a ON fa.actor_id = a.actor_id

Это производит все фильмы и их актеров, включая все фильмы без актеров, а также актеров без фильмов. Чтобы эмулировать это только с помощью неявных объединений, вам понадобятся объединения.

      -- Inner join part
SELECT f.title, a.first_name, a.last_name
FROM film f, film_actor fa, actor a
WHERE f.film_id = fa.film_id
AND fa.actor_id = a.actor_id

-- Left join part
UNION ALL
SELECT f.title, null, null
FROM film f
WHERE NOT EXISTS (
  SELECT 1
  FROM film_actor fa
  WHERE fa.film_id = f.film_id
)

-- Right join part
UNION ALL
SELECT null, a.first_name, a.last_name
FROM actor a
WHERE NOT EXISTS (
  SELECT 1
  FROM film_actor fa
  WHERE fa.actor_id = a.actor_id
)

Это быстро станет очень неэффективным как синтаксически, так и с точки зрения производительности.

Использование Joins:

SELECT a.MainID, b.SubValue AS SubValue1, b.SubDesc AS SubDesc1, c.SubValue AS SubValue2, c.SubDesc AS SubDesc2
FROM MainTable AS a
LEFT JOIN SubValues AS b ON a.MainID = b.MainID AND b.SubTypeID = 1
LEFT JOIN SubValues AS c ON a.MainID = c.MainID AND b.SubTypeID = 2

Я не вижу способа получить те же результаты, что и при использовании простого предложения WHERE для объединения таблиц. Кроме того, синтаксис, обычно используемый в предложениях WHERE для выполнения левого и правого объединений (*= и =*), постепенно сокращается,

Каждый раз, когда вы хотите объединить результаты двух таблиц, вам нужно присоединиться к ним. Взять, к примеру:

Таблица пользователей:

ID
FirstName
LastName
UserName
Password

и таблица адресов:

ID
UserID
AddressType (residential, business, shipping, billing, etc)
Line1
Line2
City
State
Zip

где у одного пользователя может быть указан его домашний И его служебный адрес (или адрес доставки и платежный адрес), или вообще нет адреса. Используя простой WHERE Предложение не будет выбирать пользователя без адресов, потому что адреса находятся в другой таблице. Чтобы получить адреса пользователя сейчас, вам нужно выполнить объединение как:

SELECT *
FROM Users
LEFT OUTER JOIN Addresses
    ON Users.ID = Addresses.UserID
WHERE Users.UserName = "foo"

См. http://www.w3schools.com/Sql/sql_join.asp для более подробного определения различных объединений и того, как они работают.

Другие вопросы по тегам