AND and OR Precedence
SQLFilteringJuniorMidUpdated
Return the orders that are shipped or delivered and have a total over 100.
Schema
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
status TEXT NOT NULL, -- 'pending', 'shipped', 'delivered', 'cancelled'
total NUMERIC NOT NULL
);Drill This: Your Query First
The Correct Query
Option (c)
SELECT id, status, total
FROM orders
WHERE (status = 'shipped' OR status = 'delivered') AND total > 100;AND binds tighter than OR, so (a) reads as status = 'shipped' OR (status = 'delivered' AND total > 100) and returns every shipped order whatever its total. The parentheses in (c) group the two statuses first. (b) can never be true, because one row has one status. (d) is an error in Postgres: 'delivered' cannot be read as a boolean, so it cannot be an operand of AND or OR.
Going Deeper
status IN ('shipped', 'delivered') says the same thing as the parenthesized OR and reads better as the list grows. When a WHERE clause mixes AND and OR, add parentheses even where precedence already does what you want, so the next reader doesn't have to remember the rule.
The Options That Fail
The explanation above says why each of these breaks.
Option (a)
SELECT id, status, total
FROM orders
WHERE status = 'shipped' OR status = 'delivered' AND total > 100;Option (b)
SELECT id, status, total
FROM orders
WHERE status = 'shipped' AND status = 'delivered' AND total > 100;Option (d)
SELECT id, status, total
FROM orders
WHERE status = 'shipped' OR 'delivered' AND total > 100;