Inner Join vs Natural Join vs USING предложение: есть ли какие-либо преимущества?

представьте, что у меня есть две простые таблицы, такие как:

CREATE TABLE departments(dept INT PRIMARY KEY, name);
CREATE TABLE employees(id PRIMARY KEY, fname, gname,
    dept INT REFERENCES departments(dept));

(упрощенно, конечно).

у меня может быть любое из следующих утверждений:

SELECT * FROM employees e INNER JOIN departments d ON e.dept=d.dept;
SELECT * FROM employees e NATURAL JOIN departments d;
SELECT * FROM employees e JOIN departments d USING(dept);

рабочий пример можно посмотреть здесь: Скрипка SQL: http://sqlfiddle.com#!15 / 864a5/13/10

все они дают почти одинаковые результаты-конечно, те же строки.

Я всегда предпочитал первую форму из-за ее гибкости, читаемости и предсказуемости - вы четко определяете, что с чем связано.

теперь, помимо того, что первая форма имеет дублированный столбец, есть ли реальное преимущество для двух других форм? Или это просто синтаксический сахар?

Я вижу недостаток в последних формах в том, что вы, как ожидается, назвали свои первичные и внешние ключи одинаковыми, что не всегда практично.

5 ответов


теперь, помимо того, что первая форма имеет дублированный столбец, есть ли реальное преимущество для двух других форм? Или это просто синтаксический сахар?

TL; DR NATURAL JOIN используется в определенном стиле реляционного программирования, который проще обычного стиля SQL. (Хотя при внедрении в SQL он обременен остальной частью синтаксиса SQL-запроса.) Это потому, что 1. это напрямую использует простой операторы логики предикатов, язык точности в инженерии (включая разработку программного обеспечения), науке (включая информатику) и математике, а также 2. одновременно и как вариант это напрямую использует простой операторы реляционная алгебра.

общая жалоба о естественном присоединении поскольку общие столбцы не являются явными, после изменения схемы может произойти несоответствующее сопряжение столбцов. И это может иметь место в конкретной среде развития. Но в таком случае ...--37-->требование это соединяются только определенные столбцы и естественное присоединение без проекта не подходит. Итак, эти аргументы предположим это естественное соединение используется неуместно. Кроме того, arguers даже не знать что они игнорируют требования. Такие жалобы обманчивая. (Кроме того, звукорежиссура программного обеспечения принципы проектирования приводят к не иметь интерфейсы с такими specificiatons.)

другая связанная с этим ложная ложная жалоба из того же лагеря заключается в том, что "естественное соединение даже не учитывает отношения внешнего ключа". Но!--73-->любой присоединиться есть из-за таблицы значений, не ограничения. Ограничения не нужны для запроса. Если добавляется ограничение, запрос остается правильным. Если ограничение отброшено, то запрос полагаясь на становится не так и должен быть изменен на фразу, что не рассчитывать на то, что не пришлось бы менять. Это не имеет ничего общего с естественным соединением.


вы описали разницу в действии: только одна копия каждого общего столбца возвращенный.

С есть ли правило для построения SQL-запроса из удобочитаемое описание?:

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

EG из Codd 1970:

изображенное отношение называется компонент. [...] Значение компонент(x, y,z) это часть x является непосредственным компонентом (или узлом) части y и z единицы части x нужно, чтобы собрать один блок части y.

С ответ:

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

включение строки в предикат дает утверждение aka предложение. Строки, которые делают истинное предложение, идут в таблицу, а строки, которые делают ложное предложение, остаются вне. (Таким образом, таблица утверждает предложение каждой текущей строки и не утверждает предложение каждого отсутствующего ряд.)

но каждое значение табличного выражения имеет предикат в своем выражении. Реляционная модель разработана так, что если таблицы T и U удерживайте строки, где T(...) и U(...) (соответственно) после:

  • T NATURAL JOIN U содержит строки, где T (...) И U(...)
  • T WHEREcondition содержит строки, где T(...) И условие
  • T UNION CORRESPONDING U содержит строки, где T(...) ИЛИ U(...)
  • T EXCEPT CORRESPONDING U содержит строки, где T(...) И НЕ U(...)
  • SELECT DISTINCTcolumns to keepFROM T содержит строки, где
    СУЩЕСТВУЕТ столбцы для удаления ТАКОЕ, ЧТО T(...)
  • etc

тогда как рассуждения о SQL в противном случае... не "естественно":

можно подумать о инструкции SQL SELECT алгебраически как 1. неявно RENAMEing каждого столбца C таблицы с (возможно, неявным) именем корреляции T до T.C, потом 2. Перекрестное соединение, затем 3. Ограничение на внутренний, затем 4. Ограничение где, то 5. Выступающий за "выбор", затем 6. RENAMEing на выбор, роняя T.s, затем 7. неявно переименование в drop remaining T.между T.-RENAMEings операторы алгебры можно рассматривать как логические операторы и имена таблиц, как и их предикаты: T JOIN ... vs Employee T.EMPLOYEE has name T.NAME ... AND .... Но концептуально внутри оператора SELECT находится таблица перекрестного соединения с двойным переименованием с T.Cs для имен столбцов, а внешние таблицы имеют CS для имен столбцов.

альтернативно оператор SQL SELECT можно логически рассматривать как 1. введение FORSOME T IN E вокруг всего оператора на имя корреляции T и базовое имя или подзапрос E, потом 2. ссылаясь на значение quantified T с помощью T.C сослаться на его C часть, потом 3. построение строк результатов из T.CС на С и т. д., Затем 4. присвоение имен столбцам строки результата в предложении SELECT, затем 4. выход из области FORSOMEs. Снова операторы алгебры рассматриваются как логические операторы, а имена таблиц-как их предикаты. Опять же, это концептуально имеет T.C внутри выбирает, но C снаружи с именами корреляции приходят и уходят.

эти две интерпретации SQL далеко не так просты, как просто используя JOIN или AND и т. д.,синонимы. (Вы не должны соглашаться с тем, что это проще, но это восприятие-это то, почему естественное соединение и объединение/кроме соответствующего.) (Аргументы, критикующие этот стиль вне контекста его предполагаемого использования, являются обманчивыми.)

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

я вижу недостаток в последних формах в том, что вы, как ожидается, назвали свои первичные и внешние ключи одинаковыми, что не всегда практично.

PKS (первичные ключи), FKS (внешние ключи) и другие ограничения не нужны для запроса. (Знание того, что столбец является функцией других, позволяет скалярные подзапросы, но вы всегда можете фразировать без.) Кроме того любые две таблицы могут быть объединены. Если вам нужны два столбца с одинаковым именем с естественным соединением, переименуйте их с помощью SELECT AS.


ввод JOIN по умолчанию выполняет внутреннее соединение. Итак:

SELECT * FROM employees e INNER JOIN departments d USING(dept);

эквивалентно

SELECT * FROM employees e JOIN departments d USING(dept);

и у вас будет только один столбец dept в результате.

таким же образом

SELECT * FROM employees e INNER JOIN departments d ON e.dept=d.dept;

эквивалентно

SELECT * FROM employees e JOIN departments d ON e.dept=d.dept;

но в результате у вас будет дубликат столбцов dept.

INNER JOIN легче читать, особенно если ваш запрос имеет другие типы соединений (слева или справа или..) включены в него.

A NATURAL JOIN предполагает совпадение одноименных столбцов в обеих таблицах. Поэтому вы не можете сделать NATURAL JOIN если, например, в таблице employees столбец join называется "department", а в таблице depts столбец join называется"dept"


главное преимущество NATURAL JOIN это единственное соединение SQL, которое не генерирует "повторяющиеся столбцы".

если все типы соединения, кроме NATURAL JOIN были удалены из языка SQL, он все равно будет относительно полным. NATURAL JOIN только присоединиться тип нужно.

, NATURAL JOIN не был введен в SQL до SQL92. В первые дни SQL языковые дизайнеры выбрали другие типы соединений и, как следствие, должны были найти способ борьбы с "дубликаты столбцов".

рассмотрим результат

employees e CROSS JOIN departments d

включает в себя два столбца с именем dept потому что каждая таблица содержит имена столбцов dept т. е. повторяющихся столбцов.

выбранным решением проблемы "повторяющихся столбцов" были переменные диапазона,e и d в приведенном выше примере. [Большинство SQL народные называем их 'псевдонимы', который cnfusing-за целого ряда переменных представляет собой строка, а не в таблице). язык SQL стандарт называет их "именами корреляции", хотя неясно, что означает "корреляция" в контексте. Крис Дата и в LINQ назовите их переменными диапазона, и я тоже!] При использовании "устаревших" типов соединений и опущении переменных диапазона будет использоваться имя переменной диапазона, равное имени таблицы (возможно, корень ошибки "таблица aiias"?).

используя пример OP:

SELECT * FROM employees e INNER JOIN departments d ON e.dept=d.dept;

проекция SELECT * будет containt 'дубликат столбцы.' Имена столбцов и их порядок в результате-одна из тех вещей, которые стандарт SQL не пытается решить; уже было слишком много расходящихся реализаций, чтобы попытаться стандартизировать. В SQL Server я получаю повторяющиеся имена [вздох].

вероятно, по этим причинам большинство людей SQL говорят: "Никогда не используйте SELECT *" etc. Обычный подход-указать каждый столбец и "проецировать" любые дубликаты. [Я думаю SELECT ALL BUT <set of columns> функция была бы хорошей, но я думаю, что SQL народные выиграли день.]

при использовании NATURAL JOIN, нет "повторяющихся столбцов" для "проецирования" и нет предикатов соединения, поэтому переменные диапазона не нужны. Поэтому пример OP должен быть переписан как:

SELECT * FROM employees NATURAL JOIN departments;

хотя это правда, что если использовать исключительно NATURAL JOIN и избегает всех других типов соединения, тогда переменные диапазона больше не нужны, SQL иногда все еще требует их. Используя сценарий @philipxy, " Если вам нужны два столбца с одинаковым именем с NATURAL JOIN переименовать через SELECT AS " - если в вашей реализации SQL отсутствуют общие табличные выражения, и вы вынуждены выполнять переименование в производной таблице, то SQL требует, чтобы производная таблица была назначена переменной диапазона, даже если вы никогда не будете ссылаться на нее снова!.

Lwt говорит, что каждая таблица в Примере OP имела бессмысленный guid столбец, который нужно "проецировать" для NATURAL JOIN цели:

SELECT *
  FROM ( SELECT dep, name, FROM employees ) e 
       NATURAL JOIN ( SELECT dept, fname, gname departments ) d;

в этом случае, без диапазона переменных e и d SQL не будет допустимым (вы получите ошибку разбора). Реализация SQL не нуждается в переменных диапазона (и даже если бы это было так, она могла бы генерировать заполнители внутри!) но язык SQL требует их из-за "кандалов совместимости" SQL, где никакая функция никогда не удаляется или не устаревает.


С документация Oracle:

естественное соединение-это операция соединения, которая создает неявное предложение join для вас на основе общих столбцов в двух соединяемых таблицах. Общие столбцы-это столбцы с одинаковыми именами в обеих таблицах.

естественным соединением может быть внутреннее соединение, левое внешнее соединение или правое внешнее соединение. По умолчанию используется внутреннее соединение.

п.

TableA JOIN tableB USING(column)

это, как вы отметил, просто синтаксический сахар для

TableA JOIN tableB ON tableA.column = tableB.column

NATURAL JOIN не так широко поддерживается и не является JOIN USING (т. е. не в SQL Server)

есть много аргументов в пользу того, что естественное соединение-плохая идея. Лично я думаю, что не называть явно такие вещи, как joins, - это приглашение к катастрофе.

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

по этим причинам, если вы только изучаете SQL сейчас, получите из привычки использовать их.