When should I use IN, and how is it different from writing a chain of OR equalities?
IN tests membership in a list of values. It is the readable equivalent of x = 1 OR x = 2 OR x = 3, and the optimizer usually treats the two identically — the generated plan is the same either way. The reasons to prefer IN are readability, and the fact that you can also use a subquery on the right-hand side.
CREATE TABLE tickets (
id INTEGER PRIMARY KEY,
title VARCHAR(160) NOT NULL,
status VARCHAR(20) NOT NULL,
assigned_to INTEGER
);
INSERT INTO tickets (id, title, status, assigned_to) VALUES
(1, 'Login page times out', 'open', 11),
(2, 'Invoice PDF is blank', 'open', 12),
(3, 'Export times out', 'open', NULL),
(4, 'Dark mode request', 'closed', 11),
(5, 'Slow search results', 'pending', NULL);
SELECT id, title, status
FROM tickets
WHERE status IN ('open', 'pending')
ORDER BY id;Three rows come back: 1, 2 and 3 with status open, and 5 with status pending. Ticket 4 is closed and is excluded.
Three practical differences from an OR chain. First, IN keeps the value list visually together, so a reviewer can check it at a glance instead of parsing four separate clauses. Second, IN accepts a subquery — WHERE assigned_to IN (SELECT id FROM engineers WHERE team = 'platform') — which keeps the rule in one place instead of hard-coding a list of ids. Third, and this is the one people miss, an empty IN list is a syntax error in most engines, while an empty OR chain is simply not written at all. If the list comes from application code and might be empty, guard it before building the query.
One NULL detail. WHERE x IN (1, 2, NULL) returns only rows where x is 1 or 2 — the NULL in the list cannot match anything, because the comparison with NULL is UNKNOWN. That means an IN list accidentally containing NULL behaves like a filter rather than like the universal match some people expect.