Using CASE expressions in WHERE clauses can adversely affect query performance because doing so can prevent the execution planner from identifying opportunities to use available indexes. I'll use EXPLAIN (ANALYZE) to demonstrate the potential performance difference between using CASE expressions and pure conditional logic in the WHERE clause.
The following commands establish the demonstration environment:
CREATE TABLE case_tests (
id serial PRIMARY KEY,
column1 integer);
INSERT INTO case_tests (column1)
SELECT random() * 2
FROM generate_series(1,1000000) s(n);
The first query uses CASE to determine which additional conditional test is applied:
SELECT *
FROM case_tests
WHERE CASE column1
WHEN 0 THEN id <= 100
ELSE id > 999900
END;
Running this query with EXPLAIN (ANALYZE) returned the following:
Seq Scan on case_tests (cost=0.00..21925.00 rows=500000 width=8) (actual time=0.014..87.607 rows=99 loops=1)
Filter: CASE column1 WHEN 0 THEN (id <= 100) ELSE (id > 999900) END
Rows Removed by Filter: 999901
Planning Time: 0.050 ms
Execution Time: 87.631 ms
The second query is functionally equivalent to the first, but uses pure conditional logic instead of a CASE expression:
SELECT *
FROM case_tests
WHERE (column1 = 0 AND id <= 100)
OR (column1 = 0 IS NOT TRUE AND id > 999900);
The resulting explain plan shows a total execution time about 1000 times faster than the query using CASE (0.088 ms vs. 87.631 ms):
Bitmap Heap Scan on case_tests (cost=10.38..665.39 rows=95 width=8) (actual time=0.025..0.051 rows=99 loops=1)
Recheck Cond: ((id <= 100) OR (id > 999900))
Filter: (((column1 = 0) AND (id <= 100)) OR (((column1 = 0) IS NOT TRUE) AND (id > 999900)))
Rows Removed by Filter: 101
Heap Blocks: exact=2
-> BitmapOr (cost=10.38..10.38 rows=197 width=0) (actual time=0.016..0.017 rows=0 loops=1)
-> Bitmap Index Scan on case_tests_pkey (cost=0.00..5.22 rows=106 width=0) (actual time=0.006..0.006 rows=100 loops=1)
Index Cond: (id <= 100)
-> Bitmap Index Scan on case_tests_pkey (cost=0.00..5.11 rows=91 width=0) (actual time=0.010..0.010 rows=100 loops=1)
Index Cond: (id > 999900)
Planning Time: 0.145 ms
Execution Time: 0.088 ms
WHERE column1 = 0 and condtion1 or column1 <> 0 and condition2? Why do you needCASEinstead of plain boolean logic? Arecondition1orcondition2computationally heavy? Anyway, here's the documentation link to working syntax: postgresql.org/docs/current/…UNIONto merge two queries into one, it may be more efficient in some circumstances compared to heavyCASEinWHEREclause.(column1 = 0 AND condition1) OR (column1 <> 0 AND condition2)is not equivalent to(CASE WHEN column1 = 0 THEN condition1 ELSE condition2 ENDbecause theCASEstatement will return the value ofcondition2whencolumn1 IS NULLbut the pure logical expression will returnNULL.