HAVING
The HAVING clause filters grouped results after aggregation. It is always used with GROUP BY.
Syntax
SELECT <column>, <aggregate_function>(<column>)
FROM <relation_name>
GROUP BY <column>
HAVING <condition>;Parameters
<condition>— a boolean expression evaluated after grouping and aggregation. It may reference aggregate functions directly, or aSELECTalias (an Opteryx-specific extension — see Notes).
Examples
Simple HAVING Filter
SELECT category, COUNT(*) AS count
FROM products
GROUP BY category
HAVING COUNT(*) > 5;Multiple Conditions
SELECT
customer_id,
COUNT(*) AS orders,
SUM(amount) AS total
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > 2
AND SUM(amount) > 1000;Using Aliases
Opteryx supports filtering by SELECT aliases in HAVING:
SELECT
department,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING avg_salary > 50000;Complex Aggregation
SELECT
year,
COUNT(DISTINCT customer_id) AS unique_customers,
SUM(amount) AS total_revenue
FROM orders
GROUP BY year
HAVING COUNT(DISTINCT customer_id) > 100
AND SUM(amount) > 100000;Combined with WHERE
WHERE and HAVING can be used together, filtering before and after grouping respectively:
SELECT category, COUNT(*) AS count
FROM products
WHERE price > 10
GROUP BY category
HAVING COUNT(*) > 5;Notes
HAVINGfilters groups after aggregation;WHEREfilters rows before grouping.HAVINGrequires a precedingGROUP BY.- You can filter on aggregate functions directly in the condition.
- Opteryx supports filtering by
SELECTaliases inHAVING. - To filter on a window function rather than a grouped aggregate, use
QUALIFY. Window functions cannot be combined with
GROUP BY, so they are never filterable withHAVING.