INNER JOIN и несколько имен таблиц в "FROM"

Возможный дубликат:
ВХОДНАЯ МЕЖДУНАРОДНАЯ ПРОГРАММА В ОТНОШЕНИИ WHERE; любая разница?

В чем разница между запросом INNER JOIN и неявным запросом соединения (перечисление нескольких таблиц после ключевого слова FROM)? Например:

Учитывая следующие две таблицы:

CREATE TABLE Statuses(
  id INT PRIMARY KEY,
  description VARCHAR(50)
);
INSERT INTO Statuses VALUES (1, 'status');

CREATE TABLE Documents(
  id INT PRIMARY KEY,
  statusId INT REFERENCES Statuses(id)
);
INSERT INTO Documents VALUES (9, 1);

В чем разница между этими двумя SQL-запросами? Из теста, который я сделал, они возвращают тот же результат. Они делают то же самое? Существуют ли ситуации, когда они возвращают разные результирующие наборы?

SELECT s.description FROM Documents d, Statuses s WHERE d.statusId = s.id AND d.id = 9;

SELECT s.description FROM Documents d INNER JOIN Statuses s ON d.statusId = s.id WHERE d.id = 9;

Ответ 1

Нет причин использовать неявное соединение (одно с запятыми). Да для внутренних объединений он вернет те же результаты. Тем не менее, он подвержен непреднамеренным перекрестным соединениям, особенно в сложных запросах, и это сложнее для обслуживания, потому что синтаксис левого/правого внешнего соединения (устаревший на SQL Server, где он не работает правильно сейчас) в любом случае отличается от поставщика к поставщику. Поскольку вы не должны смешивать неявные и эксплицированные соединения в одном запросе (вы можете получить неправильные результаты), нужно что-то изменить на левое соединение, чтобы переписать весь запрос.

Ответ 2

Если вы сделаете это первым способом, люди в возрасте до 30 лет, вероятно, посмеиваются над вами, но пока вы выполняете внутреннее соединение, они дают одинаковый результат, и оптимизатор будет генерировать один и тот же план выполнения ( по крайней мере, насколько я когда-либо мог сказать).

Это, конечно, предполагает, что предложение where в первом запросе - это то, как вы присоединяетесь ко второму запросу.

Это, вероятно, будет закрыто как дубликат, т. к.

Ответ 3

Хорошей частью второго метода является то, что он помогает отделить условие соединения (от...) от условия фильтра (где...). Это может помочь сделать чтение запроса более понятным.

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

Условие фильтра более подробно описывает конкретную задачу, выполняемую запросом. Если запрос FindRichPeople, предложение where может быть "там, где зарплата .Salary > 1000000"... описывает задачу под рукой, а не структуру базы данных.

Обратите внимание, что компилятор SQL не видит его таким образом... если он решит, что будет быстрее перекрестно присоединяться, а затем фильтровать результаты, он будет пересекать объединение и фильтровать результаты. Ему все равно, что находится в предложении ON и что в предложении WHERE. Но, как правило, это не произойдет, если предложение on соответствует внешнему ключу или присоединяется к первичному ключу или индексированному столбцу. Что касается правильной работы, они идентичны; насколько написано читаемый, поддерживаемый код, второй способ, вероятно, немного лучше.

Ответ 4

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

Ответ 5

Первый из них выполняет декартово произведение на всю запись в этих двух таблицах, а затем фильтрует по предложению where.

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

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

Ответ 7

В приведенном примере запросы эквивалентны; если вы используете SQL Server, запустите запрос и отобразите фактический план выписки, чтобы увидеть, что делает сервер внутри.