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 name or on other calculated totals.
  • Multiple conditions can be separated by commas or combined with and / or inside 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.