Старый синтаксис с простым перечислением таблиц и использованием предложения WHERE
для указания критериев соединения считается устаревшим в большинстве современных баз данных.
Это не просто для галочки, старый синтаксис может быть двусмысленным, если вы используете как INNER, так и OUTER соединения в одном запросе.
Позвольте привести пример.
Предположим, в вашей системе есть 3 таблицы:
Company
Department
Employee
Каждая таблица содержит множество строк, связанных вместе. У вас есть несколько компаний, и в каждой компании может быть несколько отделов, и в каждом отделе может быть несколько сотрудников.
Итак, теперь вы хотите сделать следующее:
Составьте список всех компаний, включая все их отделы и всех их сотрудников. Обратите внимание, что в некоторых компаниях еще нет отделов, но убедитесь, что вы их тоже включили. Убедитесь, что вы извлекаете только отделы, в которых есть сотрудники, но всегда указываете все компании.
Итак, вы делаете это:
SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
AND Department.ID = Employee.DepartmentID
Обратите внимание, что последний из них является внутренним соединением, чтобы соответствовать критериям, согласно которым вам нужны только отделы с людьми.
Итак, что теперь происходит. Проблема в том, что это зависит от движка базы данных, оптимизатора запросов, индексов и статистики таблиц. Позволь мне объяснить.
Если оптимизатор запросов определяет, что способ сделать это - сначала взять компанию, затем найти отделы, а затем выполнить внутреннее соединение с сотрудниками, вы не получите никаких компаний, у которых нет отделов.
Причина в том, что предложение WHERE
определяет, какие строки попадают в окончательный результат, а не отдельные части строк.
И в этом случае из-за левого соединения столбец Department.ID будет NULL, и поэтому, когда дело доходит до INNER JOIN для Employee, нет способа выполнить это ограничение для строки Employee, и поэтому оно не будет появляться.
С другой стороны, если оптимизатор запросов решит сначала заняться объединением отдела и сотрудника, а затем выполнить левое соединение с компаниями, вы увидите их.
Итак, старый синтаксис неоднозначен. Невозможно указать, что вы хотите, без подсказок запроса, а некоторые базы данных вообще не имеют возможности.
Введите новый синтаксис, вы можете выбрать его.
Например, если вам нужны все компании, как указано в описании проблемы, вы должны написать следующее:
SELECT *
FROM Company
LEFT JOIN (
Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
) ON Company.ID = Department.CompanyID
Здесь вы указываете, что хотите, чтобы соединение отдел-сотрудник выполнялось как одно соединение, а затем оставьте соединение результатов этого с компаниями.
Кроме того, предположим, что вам нужны только отделы, в названии которых есть буква X. Опять же, при объединении в старом стиле вы также рискуете потерять компанию, если в ней нет отделов с X в названии, но с новым синтаксисом вы можете сделать это:
SELECT *
FROM Company
LEFT JOIN (
Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'
Это дополнительное предложение используется для объединения, но не является фильтром для всей строки. Таким образом, строка может отображаться с информацией о компании, но может содержать NULL во всех столбцах отделов и сотрудников для этой строки, потому что для этой компании нет отдела с X в названии. Со старым синтаксисом это сложно.
Вот почему, среди других поставщиков, Microsoft отказалась от старого синтаксиса внешнего соединения, но не от старого синтаксиса внутреннего соединения, начиная с SQL Server 2005 и более поздних версий. Единственный способ поговорить с базой данных, работающей на Microsoft SQL Server 2005 или 2008, используя синтаксис внешнего соединения старого стиля, - это установить эту базу данных в режим совместимости 8.0 (также известный как SQL Server 2000).
Кроме того, старый способ, добавив в оптимизатор запросов кучу таблиц с кучей предложений WHERE, был сродни высказыванию «вот, пожалуйста, сделайте все, что в ваших силах». С новым синтаксисом оптимизатору запросов остается меньше работы, чтобы выяснить, какие части идут вместе.
Вот и все.
LEFT и INNER JOIN - это волна будущего.
person
Lasse V. Karlsen
schedule
21.05.2009