Aggregate facts are computed per group.

highlighted = computed this step

Aggregate facts

Each group gets exact COUNT and SUM facts before HAVING runs.

aggregate facts before filter\text{aggregate facts before filter}

Read aggregate rows

The model computes 2 aggregate facts for each of 3 groups.

aggregates=2\text{aggregates}=2

HAVING examples are tiny finite group-filter transforms; SQL dialect completeness, optimizer behavior, indexing, and product claims are out of scope.

COUNT and SUM per group: base rowsidregionstatusqty1eastopen22eastopen33westopen14westclosed45northNULL26northopen1 WHERE before groupingsourceinputwhereTruthgroupedRole0[1, east, open, 2]TRUEgrouped1[2, east, open, 3]TRUEgrouped2[3, west, open, 1]TRUEgrouped3[4, west, closed, 4]TRUEgrouped4[5, north, NULL, 2]TRUEgrouped5[6, north, open, 1]TRUEgrouped GROUP BY bucketskeysourceRowsrowCount[east][0, 1]2[west][2, 3]2[north][4, 5]2 Aggregate facts per groupkeysourceRowsaggregates[east][0, 1]{n:2, total_qty:5}[west][2, 3]{n:2, total_qty:5}[north][4, 5]{n:2, total_qty:3} HAVING result per groupkeypredicatetruthoutputRole[east]noneTRUEkept[west]noneTRUEkept[north]noneTRUEkept HAVING output groupsregionntotal_qtyeast25west25north23 HAVING factsfactvalueinputRowCount6whereKeptRows6whereDroppedRows0groupCount3aggregateCount2outputGroupCount3havingTrueCount3havingFalseCount0havingUnknownCount0groupOrderfirst_seen_after_wherepipelineWHERE_before_GROUP_BY_then_HAVING

Facts are per group

HAVING reads these group facts, not individual source-row cells.

HAVING reads aggregates\text{HAVING reads aggregates}

Summary

This book keeps only COUNT rows and integer SUM.

COUNT and SUM only\text{COUNT and SUM only}