groupBy: having

Purpose

The having key lets you filter the already grouped rows using aggregate conditions. Think of it as a WHERE for aggregates like COUNT, AVG, SUM, MIN, and MAX.

Basic Example

use Lib\Prisma\Classes\Prisma;

$prisma = Prisma::getInstance();

$result = $prisma->user->groupBy([
    'by' => ['country'],
    '_sum' => ['profileViews' => true],
    'having' => [
        '_sum' => [
            'profileViews' => ['gt' => 1000] // Only groups whose SUM(profileViews) > 1000
        ]
    ]
]);

echo "<pre>" . print_r($result, true) . "</pre>";

Complex Example (AVG inside having)

Combine multiple aggregates and conditions:

use Lib\Prisma\Classes\Prisma;

$prisma = Prisma::getInstance();

$groups = $prisma->user->groupBy([
    'by' => ['country'],
    '_avg' => ['profileViews' => true],
    '_count' => ['id' => true],
    'where' => [
        'email' => ['contains' => 'prisma.io'],
    ],
    'having' => [
        '_avg' => [
            'profileViews' => ['gt' => 100]
        ],
        '_count' => [
            'id' => ['gte' => 10]
        ]
    ],
    'orderBy' => ['country' => 'asc']
]);

echo "<pre>" . print_r($groups, true) . "</pre>";

Shape of having

The structure mirrors your aggregate keys:

  • having['_sum']['field'] => ['gt' => 100]
  • having['_avg']['price'] => ['lte' => 50]
  • having['_count']['id'] => ['gte' => 5]
  • Operators are the same ones you use in where (equals, gt, gte, lt, lte, in, etc.).

Important Notes

  • by is required. Without it, grouping cannot happen.
  • You can combine where (pre-group filtering) and having (post-group filtering).
  • Aliases in SQL are generated as {aggregate}_{field}, e.g. sum_sales, avg_price. Your output objects follow the same structure you passed in.
  • orderBy, take, and skip still work after the grouping/having phase.