CASE

Learn how to use the PostgreSQL CASE expression to add if-else branching logic directly inside SELECT, WHERE, GROUP BY, and ORDER BY clauses.

5 min read · Last updated: March 2026 · Back to overview

Quick Answer

The PostgreSQL CASE expression adds conditional logic to a query, similar to an if/else statement. It evaluates a list of WHEN conditions in order and returns the result for the first condition that is true. If no condition matches, CASE returns the ELSE result or NULL if no ELSE is provided.

Spin up a Postgres database in 20 seconds with Vela.

Try Vela Sandbox

The CASE expression is SQL's way of expressing conditional logic. Because it is an expression rather than a statement, you can place it anywhere a value is expected—inside SELECT, WHERE, GROUP BY, ORDER BY, and aggregate functions.

General CASE expression

The general form evaluates each WHEN condition as a Boolean and returns the first matching result:

CASE
  WHEN condition_1 THEN result_1
  WHEN condition_2 THEN result_2
  ...
  ELSE else_result
END

For example, classifying films by length:

SELECT
  title,
  length,
  CASE
    WHEN length > 0   AND length <= 50  THEN 'Short'
    WHEN length > 50  AND length <= 120 THEN 'Medium'
    WHEN length > 120                   THEN 'Long'
  END AS duration
FROM film
ORDER BY title;

Output (first few rows):

        title         | length | duration
----------------------+--------+----------
 Academy Dinosaur     |     86 | Medium
 Ace Goldfinger       |     48 | Short
 African Egg          |    130 | Long

Simple CASE expression

The simple form compares one expression against several values, similar to a switch statement:

CASE expression
  WHEN value_1 THEN result_1
  WHEN value_2 THEN result_2
  ...
  ELSE else_result
END

For example, expanding MPAA rating codes into descriptions:

SELECT
  title,
  rating,
  CASE rating
    WHEN 'G'     THEN 'General Audiences'
    WHEN 'PG'    THEN 'Parental Guidance Suggested'
    WHEN 'PG-13' THEN 'Parents Strongly Cautioned'
    WHEN 'R'     THEN 'Restricted'
    WHEN 'NC-17' THEN 'Adults Only'
  END AS rating_description
FROM film
ORDER BY title;

CASE with aggregate functions

A common pattern is to use CASE inside SUM or COUNT to pivot row data into columns:

SELECT
  SUM(CASE WHEN rental_rate = 0.99 THEN 1 ELSE 0 END) AS "Economy",
  SUM(CASE WHEN rental_rate = 2.99 THEN 1 ELSE 0 END) AS "Mass",
  SUM(CASE WHEN rental_rate = 4.99 THEN 1 ELSE 0 END) AS "Premium"
FROM film;

Output:

 Economy | Mass | Premium
---------+------+---------
     341 |  323 |     336

Practical tips

  • Always provide an ELSE clause to handle unexpected values; without it, unmatched rows return NULL.
  • Conditions are evaluated top to bottom—put the most selective or common cases first for readability.
  • Use CASE in ORDER BY to implement custom sort orders without changing the data model.
  • The simple form (CASE expression WHEN value...) only supports equality—use the general form for range checks, IS NULL, and other conditions.

Continue in Conditional Expressions & Operators: COALESCE.

Related in this section: COALESCE · ISNULL · NULLIF

Frequently Asked Questions

What does the PostgreSQL CASE expression do?

CASE evaluates a list of conditions and returns the result associated with the first condition that is true. It is the SQL equivalent of an if/else or switch statement and can appear anywhere a value expression is valid.

What is the difference between the general and simple CASE forms?

The general form (CASE WHEN condition THEN result ...) evaluates arbitrary Boolean conditions. The simple form (CASE expression WHEN value THEN result ...) compares a single expression to a list of values using equality. Use the general form for ranges, IS NULL checks, and complex logic.

What happens if no WHEN condition matches and there is no ELSE?

The CASE expression returns NULL. To avoid unexpected NULLs in results, always add an ELSE clause with a sensible default value.

Can I use CASE in a WHERE clause?

Yes. CASE can be used anywhere an expression is valid, including WHERE clauses. However, filtering on a CASE expression usually prevents index use, so consider restructuring the logic with OR conditions when performance matters.

How do I use CASE to pivot rows into columns?

Combine CASE with aggregate functions: use CASE to assign a 1 or 0 based on a condition, then wrap it in SUM() to count matching rows per category. This is the standard SQL approach to conditional aggregation.