Informix Error -304
-304 HAVING can only have expressions with aggregates or columns
in GROUP BY clause.The HAVING clause is used to select completed rows after grouping has been done. Therefore, the only selected values that it can test are values that are available in completed groups of rows, namely the single columns that are named in the GROUP BY clause and aggregate values. Review the HAVING clause with this rule in mind. If you want to select particular rows before grouping has taken place, use the WHERE clause.
Oninit® Troubleshooting Guidance
Reasons / Common Causes
-304 is the mirror image of -303: a HAVING clause can only reference values that actually
exist once a group is finished — an aggregate function, or a column that's part of the GROUP BY list. Any other bare column reference in HAVING isn't meaningful, because a completed group
can represent many rows with different values for that column.
- A
HAVINGclause referencing a column that isn't in theGROUP BYlist and isn't wrapped in an aggregate — the direct cause. - Confusing
WHEREandHAVING— a row-level filtering condition (that should run before grouping) was mistakenly placed inHAVINGinstead ofWHERE. - A
GROUP BYclause edited without updating aHAVINGclause that referenced one of the removed columns — a maintenance mismatch between the two clauses.
Solutions / Resolution
- Move row-level filtering conditions into
WHERE, per the official guidance —HAVINGis only for post-grouping filters on aggregates or grouped columns. - If the column genuinely needs to appear in
HAVING, add it to theGROUP BYlist, or wrap it in an appropriate aggregate function if a representative value is what's actually needed. - After editing a
GROUP BYclause, review anyHAVINGclause on the same query for columns that no longer match.
Examples
A row-level filter mistakenly placed in HAVING
SELECT region, COUNT(*) FROM orders
GROUP BY region
HAVING order_date >= '2026-01-01';
-- -304: order_date isn't in GROUP BY and isn't aggregated
Fix — move the row-level condition to WHERE:
SELECT region, COUNT(*) FROM orders
WHERE order_date >= '2026-01-01'
GROUP BY region;
A column reference that needs to be aggregated instead
SELECT region, COUNT(*) FROM orders
GROUP BY region
HAVING customer_name = 'Acme Corp';
-- -304: customer_name isn't in GROUP BY and isn't aggregated
Fix — wrap it in an aggregate, or add it to GROUP BY if it should define its own grouping level:
SELECT region, customer_name, COUNT(*) FROM orders
GROUP BY region, customer_name
HAVING customer_name = 'Acme Corp';
Diagnostic Checks
- Check every column referenced in the
HAVINGclause against theGROUP BYlist — each must either be grouped or wrapped in an aggregate. - Ask whether the condition is genuinely row-level (belongs in
WHERE) or group-level (belongs inHAVING) — this is often the actual source of the mismatch.
Related Errors / Related Topics
- -303 — "Expression mixes columns with aggregates." The
WHERE-side counterpart of this same row-level-vs-group-level distinction. - -294 — "The column column-name must be in the GROUP BY list." The general rule this
HAVING-specific restriction extends.
If a condition needs to run before grouping, it belongs in WHERE; if it needs to test an
aggregate or a grouped column after grouping, it belongs in HAVING — never a bare ungrouped
column in the latter.