В чем разница между этими двумя запросами, когда они получают два разных набора результатов? - PullRequest
3 голосов
/ 13 октября 2010

Я получаю разные результаты для этих двух запросов, и второй набор результатов представляется правильным.В чем разница в этих запросах.

Какой тип второго запроса внутреннего соединения?

1)

FROM TABLE1 t1
 INNER JOIN TABLE2 t2 ON t1.Id = t2.Id
WHERE
 t1.StatusId = 12

2)

FROM TABLE1 t1
 INNER JOIN TABLE2 t2 ON t1.Id = t2.Id
 AND t1.StatusId = 12

Ответы [ 6 ]

8 голосов
/ 14 октября 2010

Это действительно не имеет значения, когда вы делаете это в INNER JOIN.

Однако, когда вы используете LEFT или RIGHT JOIN, не имеет значения , если вы добавили дополнительный фильтр в JOIN или в предложение WHERE.

Когда вы помещаете фильтр в предложение WHERE, SQL Server сначала выполняет объединение, а затем полностью отфильтровывает строки, к которым фильтр не подходит.
-> это уменьшит количество возвращаемых строк

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

Сложно объяснить ... чтобы прояснить ситуацию, вот пример:

Взять пример данных из Ответ RedFilter :

CREATE TABLE [dbo].[t1](
    [ID] [int] NULL,
    [StatusID] [int] NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[t2](
    [ID] [int] NULL
) ON [PRIMARY]
INSERT INTO t1 (ID, StatusID) VALUES (1, 10)
INSERT INTO t1 (ID, StatusID) VALUES (2, 11)
INSERT INTO t1 (ID, StatusID) VALUES (3, 12)
INSERT INTO t1 (ID, StatusID) VALUES (4, 12)
INSERT INTO t2 (ID) VALUES (1)
INSERT INTO t2 (ID) VALUES (3)
INSERT INTO t2 (ID) VALUES (5)

... и выполните на нем следующие запросы:

/* this returns four rows, but only two will have data 
from the second table in the second column */
SELECT t1.ID, t2.ID
FROM t1 
LEFT JOIN t2 ON t1.Id = t2.Id 

/* this returns only one row: the one where t2.ID = 1 */
SELECT t1.ID, t2.ID
FROM t1 
LEFT JOIN t2 ON t1.Id = t2.Id 
WHERE t2.ID = 1 

/* this returns four rows as in the first query, but only one 
row will have data in the second column: the one where t2.ID = 1 */
SELECT t1.ID, t2.ID
FROM t1 
LEFT JOIN t2 ON t1.Id = t2.Id 
AND t2.ID = 1 

Обратите внимание на разные результаты, как указано в комментариях.

7 голосов
/ 13 октября 2010

Эти запросы должны возвращать идентичные результаты. Пожалуйста, оставьте полный запрос.

Ниже приведен пример, демонстрирующий одинаковый выход из двух вариантов:

Пример:

CREATE TABLE [dbo].[t1](
    [ID] [int] NULL,
    [StatusID] [int] NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[t2](
    [ID] [int] NULL
) ON [PRIMARY]
INSERT INTO t1 (ID, StatusID) VALUES (1, 10)
INSERT INTO t1 (ID, StatusID) VALUES (2, 11)
INSERT INTO t1 (ID, StatusID) VALUES (3, 12)
INSERT INTO t1 (ID, StatusID) VALUES (4, 12)
INSERT INTO t2 (ID) VALUES (1)
INSERT INTO t2 (ID) VALUES (3)
INSERT INTO t2 (ID) VALUES (5)

SELECT t1.ID, t1.StatusID
FROM t1 
INNER JOIN t2 ON t1.Id = t2.Id 
WHERE t1.StatusId = 12 

SELECT t1.ID, t1.StatusID
FROM t1 
INNER JOIN t2 ON t1.Id = t2.Id 
    AND t1.StatusId = 12 

Выход:

ID          StatusID
----------- -----------
3           12

(1 row(s) affected)

ID          StatusID
----------- -----------
3           12

(1 row(s) affected)
3 голосов
/ 14 октября 2010

Глядя на историю редактирования вопроса, выясняется, что ваши запросы соответствуют следующим строкам.

Запрос первый

  INNER JOIN dbo.T2
        ON ...
    LEFT OUTER  JOIN dbo.T3
        ON  ...
    WHERE 
     T3.col = somevalue AND ...

Запрос второй

  INNER JOIN dbo.T2
        ON ...
    LEFT OUTER  JOIN dbo.T3
        ON  ... AND T3.col = somevalue
   WHERE 
        ... 

Разница между ними заключается в том, что Query One эффективно преобразует LEFT Join в INNER Join.

Для левого внешнего соединения концептуально происходит следующее.

  1. T2 присоединяется к T3 и оценивается предикат в предложении соединения.
  2. Любые несоответствующие строки из T2 добавляются обратно со значениями NULL для значений столбца T3.
  3. Применяется предложение WHERE.

Ни одна из этих строк, добавленных на шаге 2, не будет соответствовать предикату T3.col = somevalue на шаге 3, поскольку мы знаем, что значение этого столбца для всех этих строк равно NULL.

1 голос
/ 13 октября 2010

SQL является декларативным языком, и СУБД должна выполнить ваш запрос. Оптимизатору запросов SQL Server не важно, объедините ли вы две таблицы, используя выражение JOIN, выражение WHERE, выражение IN или выражение EXISTS, внутренне они обрабатываются одинаково. SQL Server имеет 3 различных алгоритма внутреннего соединения, которые выбираются только на основе количества строк и распределения данных, а не точного синтаксиса, используемого для их объявления. Если вы сравните планы выполнения двух запросов в вашем примере, вы обнаружите, что они идентичны и, следовательно, будут давать одинаковый набор результатов.

0 голосов
/ 14 октября 2010

Разница под капотом заключается в том, что предложение WHERE доступно после всех соединений.

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

Пожалуйста, смотрите эту ссылку: http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/

0 голосов
/ 13 октября 2010

Я считаю, что это так:

Первый запрос получает все результаты из объединенных таблиц, а затем фильтрует предложение WHERE.

Второй запрос получает результаты из таблицы 1, где StatusID = 12, а затем выполняет объединение набора результатов.

Это тонкая разница.

Edit: Вот ссылка на статью, подтверждающую разницу: http://www.sqlteam.com/article/additional-criteria-in-the-join-clause

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