Как могло случиться, что эти два запроса разрешаются в одном и том же выводе?
SELECT *
FROM [dbo].[Orders]
where 1=1
AND year(OrderDate) = 1998
AND MONTH(OrderDate) = 5
OR year(OrderDate) = 1997
AND MONTH(OrderDate) = 4
SELECT *
FROM [dbo].[Orders]
where 1=1
AND (year(OrderDate) = 1998 AND MONTH(OrderDate) = 5)
OR (year(OrderDate) = 1997 AND MONTH(OrderDate) = 4)
Я ожидал, что они отложат, так как второй запрос явно генерирует 2 популяции: заказы от 05.1998 и 04.1997. Первый запрос каким-то образом делает то же самое...
Кроме того, важно использовать предложения SARGable. Вы действительно должны использовать границы даты, а не использовать операторы YEAR
и MONTH
в столбце в WHERE
.
Большая разница между w AND x AND y OR z
и w AND (x AND y) OR (z)
и w AND ((x and y) OR (z))
. AND
выигрывает.
Вы хотите использовать:
where 1=1
AND
(
(
OrderDate >= '19980501'
AND OrderDate < '19980601'
)
OR
(
OrderDate >= '19970401'
AND OrderDate < '19970501'
)
)
Как предложил Ларну, см. тему Приоритет оператора, чтобы узнать, как ведут себя AND
и OR
, и как управлять желаемым поведением, группируя предикаты в круглых скобках.
Если вы принимаете во внимание приоритет оператора и круглые скобки, оба ваших условия эквивалентны
WHERE (1=1 and year = 1998 and month = 5) or
(year = 1997 and month = 4)
Но поскольку 1=1
всегда верно, а true AND x AND y
эквивалентно x AND y
, вы можете удалить 1=1
, таким образом, оба ваших условия на самом деле
WHERE (year = 1998 and month = 5) or
(year = 1997 and month = 4)
OR
s, важно использовать скобки для обозначения нужной вам логики.