Разница между "и" и "где" в соединениях - PullRequest
16 голосов
/ 01 апреля 2010

Какая разница между

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON     cd.Company = table2.Name 
       and table2.Id IN (2728) 

и

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON cd.Company = table2.Name 
 where table2.Id IN (2728) 

оба возвращают один и тот же результат, и оба имеют одинаковый вывод объяснения

Ответы [ 5 ]

30 голосов
/ 01 апреля 2010

Во-первых, есть смысловая разница. Когда у вас есть соединение, вы говорите, что связь между двумя таблицами определяется этим условием. Итак, в своем первом примере вы говорите, что таблицы связаны cd.Company = table2.Name AND table2.Id IN (2728). Когда вы используете предложение WHERE, вы говорите, что отношение определяется cd.Company = table2.Name и вам нужны только те строки, к которым применяется условие table2.Id IN (2728). Даже если они дают один и тот же ответ, для программиста, читающего ваш код, это очень разные вещи.

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

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

Вот пример, демонстрирующий это.

Запрос 1 (ГДЕ):

SELECT DISTINCT field1
  FROM table1 cd
  LEFT JOIN table2
    ON cd.Company = table2.Name
 WHERE table2.Id IN (2728);

Результат:

field1
200

Запрос 2 (И):

SELECT DISTINCT field1
  FROM table1 cd
  LEFT JOIN table2
    ON cd.Company = table2.Name
   AND table2.Id IN (2728);

Результат:

field1
100
200

Используемые данные испытаний:

CREATE TABLE table1 (Company NVARCHAR(100) NOT NULL, Field1 INT NOT NULL);
INSERT INTO table1 (Company, Field1) VALUES
('FooSoft', 100),
('BarSoft', 200);

CREATE TABLE table2 (Id INT NOT NULL, Name NVARCHAR(100) NOT NULL);
INSERT INTO table2 (Id, Name) VALUES
(2727, 'FooSoft'),
(2728, 'BarSoft');
6 голосов
/ 01 апреля 2010

SQL происходит от реляционной алгебры .

Одним из способов увидеть разницу является то, что JOIN - это операции над наборами, которые могут дать больше записей или меньше записей в результате, чем вы имели в исходных таблицах. С другой стороны, ГДЕ всегда будет ограничивать количество результатов.

Остальная часть текста является дополнительным объяснением.


Обзор типов соединений см. article снова.

Когда я сказал, что условие where всегда будет ограничивать результаты, вы должны принять во внимание, что когда мы говорим о запросах к двум (или более) таблицам, вы должны каким-то образом объединить записи из этих таблиц, даже если нет Ключевое слово JOIN.

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

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

Но держите, есть исключения из этого максимума, когда вы вводите соединения LEFT, RIGHT и FULL OUTER.

LEFT JOIN объединит записи из левой таблицы по заданному критерию с записями из правой таблицы, НО, если критерии объединения, просмотр строки из левой таблицы не удовлетворяет ни одной записи в правой таблице, LEFT JOIN будет по-прежнему возвращать запись из левой таблицы, а в столбцах, которые будут приходить из правой таблицы, он будет возвращать NULL (RIGHT JOIN работает аналогично, но с другой стороны, FULL OUTER работает как оба одновременно).

Поскольку перекрестное соединение по умолчанию НЕ возвращает эти записи, вы не можете выразить эти критерии объединения с условием WHERE, и вы вынуждены использовать синтаксис JOIN (исключение oracle к этому было с расширением стандарта SQL и оператора to =, но это не было принято ни другими поставщиками, ни стандартом).

Кроме того, объединения, как правило, но не всегда, совпадают с существующей ссылочной целостностью и предполагают отношения между сущностями, но я бы не придавал этому большого значения, поскольку условия where могут делать то же самое (за исключением упомянутого выше случая) и для хорошей СУБД не будет иметь значения, где вы укажете свои критерии.

3 голосов
/ 01 апреля 2010
  • Объединение используется для отражения отношений между сущностями
  • предложение where фильтрует результаты.

Таким образом, предложения объединения являются «статическими» (если отношения сущностей не изменяются),
, тогда как предложения where зависят от конкретного случая использования.

1 голос
/ 01 апреля 2010

Разницы нет. «ON» - это синоним слова «WHERE», поэтому второй вид читается как

JOIN table2 WHERE cd.Company = table2.Name AND table2.Id IN (2728)

0 голосов
/ 01 апреля 2010

Нет разницы, когда механизм оптимизации запросов разбивает его на соответствующие операторы запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...