Filtering Windows with QUALIFY in SQL
QUALIFY filters on a window function the way HAVING filters on an aggregate, in one clause with no subquery.
A window function like
row_number()
is computed after WHERE
and
GROUP BY
run, so you cannot filter on it in
WHERE. The usual fix is to wrap the query in a CTE or subquery and filter
outside.
QUALIFY
does it in one clause. It filters on a window function the same way
HAVING
filters on an aggregate, so the classic "top row per group" report needs no
extra nesting.
select category_id, product_name, price
from products
qualify row_number() over (
partition by category_id
order by price desc
) = 1 A DuckDB and warehouse feature
QUALIFY
is supported by DuckDB (which powers SQLShed), plus BigQuery, Snowflake, and
others. PostgreSQL and MySQL don't support it, so fall back to a CTE or
subquery that filters on the window column.
Schema · Garden Shop Tables · products, categories 2 tables
One row per product, with price, cost, and inventory levels.
Lookup table of product categories.
Return the most expensive product in each category: the category name, the product name, and its price. There should be exactly one row per category, sorted by category name.
Run your query to inspect the result.
Expected answer
- Columns: category_name, product_name, price.
- One row per category: eight rows, each the priciest product in that category.
- Ties are broken by product_id so exactly one row survives per group.
Related
Nested SELECTs, IN, EXISTS, and correlation.
Ranking, LAG/LEAD, and running totals at a glance.
Practice ranking, running totals, and top row per group.
The default RANGE frame groups tied rows; use ROWS.
Filter window results in a CTE or with QUALIFY.
The WITH clause, chained steps, and CTE vs subquery.