Mysql или/и приоритет?
Мне интересно, как и/или работает?
Например, если я хочу получить все строки, где display = 1
Я могу просто сделать WHERE tablename.display = 1
и если мне нужны все строки, где display = 1 или 2
Я могу просто сделать WHERE tablename.display = 1 or tablename.display = 2
Но что, если я хочу получить все строки, где display = 1 или 2, и где любой контент, теги или заголовок содержит hello world
Как будет логика для этого?
Select * from tablename
where display = 1 or display = 2 and content like "%hello world%" or tags like "%hello world%" or title = "%hello world%"
Мое предположение. но потом я могу прочитать это несколькими способами.
Зачитывается ли он как:
(display = 1 or display = 2) and (content like "%hello world%" or tags like "%hello world%" or title = "%hello world%")
или
((display = 1 or display = 2) and (content like "%hello world%")) or (tags like "%hello world%" or title = "%hello world%")
и др.
Ответы
Ответ 1
В документации MySQL есть хорошая страница с информацией о том, какие операторы имеют приоритет.
С этой страницы
12.3.1. Приоритет оператора
Приоритеты операторов показаны в следующем списке: от наивысшего приоритета до самого низкого. Операторы, которые показаны вместе на линии, имеют одинаковый приоритет.
INTERVAL
BINARY, COLLATE
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
<<, >>
&
|
= (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
&&, AND
XOR
||, OR
= (assignment), :=
Итак, ваш исходный запрос
Select
*
from tablename
where
display = 1
or display = 2
and content like "%hello world%"
or tags like "%hello world%"
or title = "%hello world%"
будет интерпретироваться как
Select
*
from tablename
where
(display = 1)
or (
(display = 2)
and (content like "%hello world%")
)
or (tags like "%hello world%")
or (title = "%hello world%")
Если вы сомневаетесь, используйте скобки, чтобы сделать ваше намерение понятным. Хотя информация на странице MySQL полезна, она может быть не сразу очевидна, если запрос когда-либо пересматривается.
Вы можете подумать о следующем. Обратите внимание, что я изменил title = "%hello world%"
на title like "%hello world%"
, так как это лучше подходит для цели, о которой вы описали.
Select
*
from tablename
where
(
(display = 1)
or (display = 2)
) and (
(content like "%hello world%")
or (tags like "%hello world%")
or (title like "%hello world%")
)
Ответ 2
Вам нужно использовать скобки для нескольких условий OR
. А для display = 1 OR display = 2
вы можете использовать display IN(1,2)
. Попробуйте следующее:
SELECT * FROM tableName
WHERE display IN (1,2)
AND (content LIKE "%hello world%"
OR tags LIKE "%hello world%"
OR title LIKE "%hello world%")
Подробнее см. MySQL: Приоритет оператора
Ответ 3
Запустите этот запрос:
select 1 or 1 and 0
Если это выглядит как 1
, то это означает, что приоритет:
select 1 or (1 and 0)
если он выходит 0
, тогда приоритет:
select (1 or 1) and 0
Спойлер: он выходит 1
То есть, AND
оценивается до OR
s или, как мне хотелось бы сказать, ANDs являются более липкими.
Ответ 4
на всех серверах SQL, AND
имеет приоритет над OR
, поэтому просто не забудьте скопировать скобки вокруг вашего OR
s:
select * from tablename
where (display = 1 or display = 2)
and (content like "%hello world%"
or tags like "%hello world%"
or title = "%hello world%")
btw (display = 1 or display = 2)
эквивалентно display in (1, 2)
.