Having
The having
method allows you to filter grouped query results based on aggregated values. Unlike where
which filters individual rows, having
filters the results after grouping and aggregation.
Basic Usage
import { createQueryBuilder } from '@hypequery/clickhouse';
const db = createQueryBuilder<Schema>();
// Filter grouped results
const query = db
.table('orders')
.select(['user_id'])
.sum('total', 'total_spent')
.groupBy(['user_id'])
.having('total_spent > 1000')
.toSQL();
// Result: SELECT user_id, SUM(total) AS total_spent FROM orders GROUP BY user_id HAVING total_spent > 1000
Type Definitions
having(condition: string, parameters?: any[]): this
Parameters
condition
: The HAVING condition as a string (e.g., ‘total_spent > 1000’)parameters
: Optional array of parameters for the condition (for parameterized queries)
Returns
Returns the query builder instance for method chaining.
Multiple Conditions
Multiple having()
calls are automatically combined with AND
operators:
.having('total_spent > 1000')
.having('order_count >= 5')
// Results in: HAVING total_spent > 1000 AND order_count >= 5
Examples
Basic Having Clause
// Filter users who spent more than $1000
const query = db
.table('orders')
.select(['user_id'])
.sum('total', 'total_spent')
.groupBy(['user_id'])
.having('total_spent > 1000')
.toSQL();
// Result: SELECT user_id, SUM(total) AS total_spent FROM orders GROUP BY user_id HAVING total_spent > 1000
Multiple Having Conditions
// Filter with multiple conditions (automatically combined with AND)
const query = db
.table('orders')
.select(['user_id'])
.sum('total', 'total_spent')
.count('id', 'order_count')
.groupBy(['user_id'])
.having('total_spent > 1000')
.having('order_count >= 5')
.toSQL();
// Result: SELECT user_id, SUM(total) AS total_spent, COUNT(id) AS order_count FROM orders GROUP BY user_id HAVING total_spent > 1000 AND order_count >= 5
Type Safety
The having
method accepts string conditions, so TypeScript validation is limited:
interface OrderSchema {
orders: {
id: 'UInt32';
user_id: 'UInt32';
total: 'Float64';
status: 'String';
};
}
const db = createQueryBuilder<OrderSchema>();
// ✅ Valid having condition
const query = db
.table('orders')
.select(['user_id'])
.sum('total', 'total_spent')
.groupBy(['user_id'])
.having('total_spent > 1000') // String condition
.toSQL();
// ⚠️ No TypeScript validation for having conditions
// The condition is passed as a string, so errors won't be caught at compile time
Important Notes
- String-based conditions: All having conditions are passed as strings, so there’s no compile-time validation
- AND combination: Multiple
having()
calls are automatically combined withAND
operators - Parameter support: Use the
parameters
array for dynamic values to prevent SQL injection - Complex conditions: For complex OR conditions, use a single
having()
call with the full condition string