ANY / ALL (subquery)
PG 7.4+→ booleanCompares a value against all results from a subquery. ANY returns true if the comparison holds for any row; ALL if it holds for every row.
Signatures
value op ANY ( subquery ) → booleanvalue op ALL ( subquery ) → booleanParameters
| Parameter | Type | Description |
|---|---|---|
| value | any | Value to compare |
| op | comparison operator | Any comparison operator: =, <, >, <=, >=, <> |
| subquery | SELECT returning single column | Set of values |
Examples
SELECT * FROM products WHERE price > ANY(SELECT price FROM products WHERE category = 'budget');Products pricier than at least one budget itemSELECT * FROM products WHERE price < ALL(SELECT price FROM products WHERE category = 'premium');Products cheaper than all premium itemsSELECT employee_id, salary FROM employees WHERE salary >= ALL(SELECT salary FROM employees WHERE department_id = 3);Employees earning at least as much as every employee in department 3SELECT id, score FROM submissions WHERE score > ANY(SELECT score FROM submissions WHERE status = 'passing' AND contest_id = 5);Submissions beating at least one passing score in contest 5`x <> ANY(subquery)` is true when x differs from at least one row — this is almost always true for any non-empty set, not what developers intend when trying to express 'not in the set'. The correct NOT IN equivalent is `<> ALL(subquery)`.
✓ Instead: Use `x <> ALL(subquery)` to express 'x is not equal to any value in the set' — the correct SQL equivalent of `NOT IN`. Use `<> ANY` only when you explicitly mean 'differs from at least one element'.
`x > ALL(subquery)` is equivalent to `x > (SELECT max(col) FROM ...)` but more readable. Similarly, `x > ANY(subquery)` = `x > (SELECT min(col) FROM ...)`. The scalar subquery form is often faster.
SELECT * FROM products WHERE price > (SELECT max(price) FROM products WHERE is_sale = true);Products priced above the highest sale price — cleaner and faster than ALLCommon Gotchas
NULL kills comparisons silently — nothing equals NULL, not even NULL
NULL = NULL is not TRUE. It is NULL. Queries filtering for NULL with = will silently return zero rows.
NOT IN with a subquery that returns any NULL always returns empty set
If a NOT IN subquery returns even one NULL value, the entire NOT IN returns no rows — silently.