Skip to content

Having (group filter)

having filters on the aggregated value, not the source rows — the SQL HAVING to a column filter’s WHERE. After the engine rolls up the tree, having keeps only the groups whose measures satisfy a safe formula-DSL predicate (e.g. "revenue > 1000"); nodes that fail are pruned, but the ancestor path to any survivor is kept so the hierarchy stays intact. It runs in the engine — the frontend does no math — and applies to the grid (row-tree) flow only.

This is best seen in a running app; the config is the whole feature:

from dash_tensor_grid import TensorGrid, build_grid
payload = build_grid(sales, {
"rows": ["region", "country"],
"measures": {"revenue": "sum", "qty": "sum"},
"formats": {"revenue": "currency:USD"},
"having": "revenue > 1000", # keep only groups whose aggregated revenue exceeds 1000
})
TensorGrid(id="grid", row_data=payload["row_data"], column_defs=payload["column_defs"])
  • Post-aggregation. The predicate is evaluated against each node’s rolled-up measures — the same safe DSL as a calculated measure, so "revenue > cost * 1.5" works too. It never runs arbitrary code.
  • Ancestors kept. A failing parent that still has a passing descendant is retained as a path; only genuinely empty branches disappear.
  • Grid flow only. having is refused on a pivot (columns) config — the cross-tab has a different shape. In lazy / server mode it prunes the shipped root level until children are fetched.
  • Contrast with a column range filter, which tests the source rows before aggregation.