Когда этот T-SQL стал неправильным? Или всегда? - PullRequest
5 голосов
/ 05 мая 2011

Почему следующие (два последних) утверждения возвращают разные результаты. Я почти на 100% уверен, что они «использовали», чтобы вернуть тот же результат (кто-нибудь помнит, как это было в SQL Server 6/2000?).

CREATE TABLE [dbo].[color](
    [colorid] [int] NOT NULL,
    [title] [varchar](255) NOT NULL
) ON [PRIMARY]
INSERT color SELECT 1,'Red' UNION ALL SELECT 2,'Green' UNION ALL SELECT 3,'Blue'

CREATE TABLE [dbo].[membercolor](
    [memberid] [int] NOT NULL,
    [colorid] [int] NOT NULL
) ON [PRIMARY]
INSERT membercolor SELECT 10,1 UNION ALL SELECT 10,2 UNION ALL SELECT 10,3 UNION ALL SELECT 11,1 UNION ALL SELECT 11,2 UNION ALL SELECT 12,1

SELECT * FROM color
SELECT * FROM membercolor

-- red, green & blue
SELECT * FROM color a LEFT JOIN membercolor b 
    ON a.colorid=b.colorid AND b.memberid=11

-- red, green - but why?    
SELECT * FROM color a LEFT JOIN membercolor b 
    ON a.colorid=b.colorid WHERE b.memberid IS NULL OR b.memberid=11

Ответы [ 3 ]

3 голосов
/ 05 мая 2011

Проверка is null работает только для colors, у которых совсем нет соответствия membercolor.

Если совпадает membercolor, вы получите набор результатов, подобный:

color blue memberid 8
color blue memberid 9
color blue memberid 10

Применение предложения where отфильтровывает все синие строки:

memberid IS NULL OR b.memberid=11

Если нет membercolor совпадений, результирующий набор выглядит так:

color blue memberid NULL

Предложение where позволит этому пройти.

2 голосов
/ 05 мая 2011

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

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

В вашем первом запросе это действительно так.Но во втором запросе во время обработки предложения FROM ему удается создать строку, соответствующую условию JOIN:

3   Blue      10    3

Таким образом, он никогда не создает строку со значениями NULL для этих столбцов из правой таблицы.

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

Как уже говорили другие, вы, возможно, помните синтаксис соединения до ANSI, который могдают удивительные результаты.

1 голос
/ 05 мая 2011

Так было всегда (по крайней мере, с 2000 г.) - чтобы понять почему, проверьте следующее утверждение:

SELECT * FROM color a LEFT JOIN membercolor b 
    ON a.colorid=b.colorid 

С другой стороны, вы могли бы подумать:

SELECT * FROM color a LEFT JOIN membercolor b 
    ON a.colorid=b.colorid AND b.memberid=11 WHERE b.memberid IS NULL OR b.memberid=11
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...