Приоритет оператора SQL Logic: и и
Являются ли эти два утверждения ниже эквивалентными?
SELECT [...]
FROM [...]
WHERE some_col in (1,2,3,4,5) AND some_other_expr
и
SELECT [...]
FROM [...]
WHERE some_col in (1,2,3) or some_col in (4,5) AND some_other_expr
Есть ли какая-то таблица истинности, которую я мог бы использовать для проверки этого?
Ответы
Ответ 1
And
имеет приоритет над Or
, так что, даже если a <=> a1 Or a2
Where a And b
это не то же самое, что
Where a1 Or a2 And b,
потому что это будет выполнено как
Where a1 Or (a2 And b)
и то, что вы хотите, чтобы сделать их одинаковыми, это следующее (использование скобок для переопределения правил приоритета):
Where (a1 Or a2) And b
Вот пример для иллюстрации:
Declare @x tinyInt = 1
Declare @y tinyInt = 0
Declare @z tinyInt = 0
Select Case When @x=1 OR @y=1 And @z=1 Then 'T' Else 'F' End -- outputs T
Select Case When (@x=1 OR @y=1) And @z=1 Then 'T' Else 'F' End -- outputs F
Для тех, кто любит обращаться за рекомендациями (в алфавитном порядке):
Ответ 2
Я добавлю 2 очка:
- "IN" - это серийные OR с круглыми скобками вокруг них.
- И имеет приоритет над ИЛИ на всех языках, которые я знаю.
Итак, 2 выражения просто не равны.
WHERE some_col in (1,2,3,4,5) AND some_other_expr
--to the optimiser is this
WHERE
(
some_col = 1 OR
some_col = 2 OR
some_col = 3 OR
some_col = 4 OR
some_col = 5
)
AND
some_other_expr
Итак, когда вы нарушаете предложение IN, вы разделяете порядковые ORs и изменяете приоритет.
Ответ 3
- Арифметические операторы
- Оператор конкатенации
- Условия сравнения
- IS [NOT] NULL, LIKE, [NOT] IN
- [NOT] BETWEEN
- Не равен
- НЕ логическое условие
- И логическое условие
- ИЛИ логическое условие
Вы можете использовать круглые скобки для переопределения правил приоритета.
Ответ 4
Запрос для отображения таблицы истинности выражения с 3 переменными:
;WITH cteData AS
(SELECT 0 AS A, 0 AS B, 0 AS C
UNION ALL SELECT 0,0,1
UNION ALL SELECT 0,1,0
UNION ALL SELECT 0,1,1
UNION ALL SELECT 1,0,0
UNION ALL SELECT 1,0,1
UNION ALL SELECT 1,1,0
UNION ALL SELECT 1,1,1
)
SELECT cteData.*,
CASE WHEN
(A=1) OR (B=1) AND (C=1)
THEN 'True' ELSE 'False' END AS Result
FROM cteData
Результаты для (A=1) OR (B=1) AND (C=1)
:
A B C Result
0 0 0 False
0 0 1 False
0 1 0 False
0 1 1 True
1 0 0 True
1 0 1 True
1 1 0 True
1 1 1 True
Результаты для (A=1) OR ( (B=1) AND (C=1) )
совпадают.
Результаты для ( (A=1) OR (B=1) ) AND (C=1)
:
A B C Result
0 0 0 False
0 0 1 False
0 1 0 False
0 1 1 True
1 0 0 False
1 0 1 True
1 1 0 False
1 1 1 True