How exactly does using OR in a MySQL statement differ with/without parentheses?
Solution 1:
This is because OR has lower operator precedence than AND. Whenever the DB sees an expression like
A AND B OR C
the AND is evaluated first, i.e. it is equivalent to
(A AND B) OR C
So if you explicitly want
A AND (B OR C)
instead, you must put in the parentheses.
This is btw not specific to SQL. The order of precedence of these operators is the same in all programming languages I know (i.e. at least C, C++, C#, Java and Unix shell scripts).
Solution 2:
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND `status` = 'active' OR `status` = 'past due'
In this example, you will get all records where either
a) The date_next_payment is before 2nd Feb 2011 AND status is active
b) The status is past_due
So the past_due records will not be restricted by date.
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
In this example, you will get all records where
a) The date_next_payment is before 2nd Feb 2011
AND
b) The status is either active or past_due
The brackets work like they do in maths or logic - the statements inside the brackets get evaluated first... so imagine seeing each step take place like this:
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
So a record is encountered with a status of active...
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (TRUE OR FALSE)
This then evaluates, with the OR condition... (TRUE OR FALSE) == TRUE
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND TRUE
And the date is 2011-01-01
SELECT * FROM (`users`) WHERE TRUE
AND TRUE
And finally, TRUE AND TRUE == TRUE
SELECT * FROM (`users`) WHERE TRUE
And so the record is returned...
Imagining your query being executed in steps like this against each row in the database sometimes helps to understand where to put your brackets.
Solution 3:
in
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND `status` = 'active' OR `status` = 'past due'
it will consider first date_next_payment <= '2011-02-02' AND status = 'active'
and then the boolean answer of this will be done OR with status = 'past due'
While in
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
First OR will be done and then And will be done... Thats y this will give the different answer
Solution 4:
The MySQL manual has a page on operator precedence. It shows that AND has a higher precedence. So p1 AND p2 OR p3
is interpreted as (p1 AND p2) OR p3
. A truth table will easily convince you that this is different from p1 AND (p2 OR p3)
.