Приоритет оператора логики SQL: и и или


179

Два утверждения ниже эквивалентны?

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

Есть ли какая-то таблица истинности, которую я мог бы использовать, чтобы проверить это?


4
Попробуйте: TT F. (T или T) и F. T или (T и F). Читатель кода должен четко понимать намерения составителя кода. И писатель должен быть уверен, что машина делает то, что он хотел. Скобки выравнивают все три: читатель, писатель и машина. :)
Асад Эбрахим

Ответы:


290

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

Для тех, кто любит обращаться за рекомендациями (в алфавитном порядке):


18
Хорошей практикой является использование скобок, даже если они не нужны. очень немногие программисты (если таковые имеются) знают приоритет всех доступных операторов.
Трисмегистос

1
@Trismegistos Хотелось бы, чтобы это было не так ... не должно быть так, но я предполагаю, что вы правы.
Чарльз Бретана

1
Это ANDтогда ORприоритет является частью стандарта SQL?
Хайме Хаблутцель

@Jaime, да, и, аааик, это тоже часть стандарта для всех языков программирования.
Чарльз Бретана

4
@Bsienn, не уверен, что вы сделали, но это не согласуется со стандартным SQL и документацией MySQL ... dev.mysql.com/doc/refman/5.0/en/operator-precedence.html Попробуйте еще раз, - осторожно время ... попробуй 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 select case when (@x=1 or @y=1) and @z=1 then'T' else 'F' end
Чарльз Бретана

33

Я добавлю 2 балла:

  • «IN» - это, по сути, последовательные ИЛИ с круглыми скобками
  • И имеет приоритет над ИЛИ на каждом языке, который я знаю

Итак, 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, вы разделяете последовательные ИЛИ и меняете приоритет.


gbn Есть ли ассоциативность в ORACLE SQL? Если ДА, то как и где я могу получить все операторы ассоциативности?
Асиф Муштак

2
Столько, сколько мне больно это говорить, И не имеет приоритета над ИЛИ в рубине! Что еще хуже, && имеет приоритет над ||! Одна из причин, по которой мне не нравится рубин - он снова и снова нарушает принцип наименьшего удивления. 2.2.1: 007> true или true и false => false 2.2.1: 008> true || true && false => true
Алекс Л

23
  1. Арифметические операторы
  2. Оператор конкатенации
  3. Условия сравнения
  4. НЕТ [НЕТ], НРАВИТСЯ, [НЕТ] В
  5. [НЕ] МЕЖДУ
  6. Не равно
  7. НЕ логическое условие
  8. И логическое условие
  9. ИЛИ логическое условие

Вы можете использовать скобки, чтобы переопределить правила приоритета.


9

Запрос, чтобы показать таблицу истинности логического выражения с 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.