having()

The having() method adds a HAVING clause to your query, used to filter grouped results. It supports aggregate functions, subquery aliases and grouped fields, and applies strict validation to prevent unsafe usage.

Signature:

public function having(string $columnOrAlias, mixed $value, string $operator = '='): self

Allowed Column Expressions

  • Columns in groupBy() (e.g. 'user_id') ✅
  • Aggregate functions like COUNT(*), SUM(amount), AVG(score)
  • Subquery aliases via $db->subQuery('alias')
  • Direct column names not in GROUP BY ❌
  • Dangerous expressions like '1 OR 1=1'

Supported Operators

  • =, !=, >, <, >=, <=
  • BETWEEN, NOT BETWEEN → requires array with exactly two values
  • IN, NOT IN → requires non-empty array
  • IS, IS NOT → only valid with null (or 'DBNULL', 'DBNOTNULL')

Special Values

  • 'DBNULL' → becomes IS NULL
  • 'DBNOTNULL' → becomes IS NOT NULL
  • Subqueries, placeholders like [F], [I] are validated and supported

Example with Aggregate Function

$db->groupBy('user_id');
$db->having('SUM(price)', 100, '>');

Example with BETWEEN

$db->groupBy('user_id');
$db->having('AVG(score)', [50, 80], 'BETWEEN');

Example with Subquery Alias

$sub = $db->subQuery('o');
$sub->get('orders');
$db->from($sub, 'user_stats');

$db->having('o', 100, '>');

Example with IS NOT NULL

$db->groupBy('customer_id');
$db->having('SUM(total)', 'DBNOTNULL', 'IS NOT');

Invalid Usage

The following will be rejected because email is not grouped, not aggregated, and not a valid alias:

// ❌ Unsafe
$db->having('email', 'x@example.com');

See Also