HAVING Clause ✂️
Use having to filter after totals are calculated — similar to where, but applied to the results of your query instead of raw rows.
Example use case: show only lines where average linespeed is between 100 and 300.
Key Points
- Filter on column names from
aggregate ... as nameor on other calculated totals. - Multiple conditions can be separated by commas or combined with
and/orinside one condition. - Quote column names that contain spaces:
having 'Uptime Hours' > 0
Example 1: Minimum Threshold
Lines with more than 0 uptime hours in the last 7 days:
aggregate timeinif(interval.state.type = 'Uptime') / 3600 as uptime_hours
where time from now()-7D to now()
group by line.name as linename
having uptime_hours > 0
Example 2: Comparing Aggregates
Lines where downtime exceeded uptime:
aggregate
timeinif(interval.state.type = 'Uptime') / 3600 as uptime_hours,
timeinif(interval.state.type = 'Downtime') / 3600 as downtime_hours
where time from now()-7D to now()
group by line.name as linename
having downtime_hours > uptime_hours
Example 3: Multiple Conditions
Lines with average linespeed between 100 and 300:
aggregate avg(metric_group('linespeed_uuid')) as avg_linespeed
where time from now()-30D to now()
group by line.name as linename
having avg_linespeed > 100 and avg_linespeed < 300
Example 4: Filtering on a labeled bucket
Put values into bands with multiIf, then filter on the band name:
aggregate
avg(metric_group('linespeed_uuid')) as avg_speed,
multiIf(
avg_speed > 200, 'Fast',
avg_speed > 100, 'Medium',
'Slow'
) as speed_band
where time from now()-7D to now()
group by line.name as linename
having speed_band = 'Fast'
WHERE vs HAVING
| Clause | When it runs | Example |
|---|---|---|
where |
Before totals — filters raw rows | where interval.state.type = 'Uptime' |
having |
After totals — filters result rows | having uptime_hours > 0 |
✨ Use where to narrow the input data; use having to narrow the answers.