DS-15755: Document LIKE and HAVING support in Analytics Engine SQL reference (#27200)

* DS-15755: Document `LIKE` pattern matching operators in Analytics Engine SQL reference

`LIKE`, `ILIKE`, `NOT LIKE`, `NOT ILIKE` are all now supported by Workers Analytics
Engine. Add docs.

* DS-15385: Add SQL `HAVING` documentation to Analytics Engine SQL reference

`HAVING` has been supported for a few weeks and soft-announced. This commit documents it.

* DS-15385: Add WAE changelog entry for `HAVING` and `LIKE` support

I'm combining the changelogs for these two small additions because they have a lot
in common and are too small to justify multiple posts at once.
This commit is contained in:
Miki Mokrysz 2026-01-06 17:02:08 +00:00 committed by GitHub
parent ea00ce69ac
commit 9277762e6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 162 additions and 3 deletions

View file

@ -0,0 +1,76 @@
---
title: Workers Analytics Engine SQL now supports filtering using HAVING and LIKE
description: Workers Analytics Engine's SQL API now supports SQL's HAVING and LIKE features
date: 2026-01-07
products:
- workers-analytics-engine
---
You can now use the `HAVING` clause and `LIKE` pattern matching operators in [Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/).
Workers Analytics Engine allows you to ingest and store high-cardinality data at scale and query your data through a simple SQL API.
## Filtering using `HAVING`
The `HAVING` clause complements the `WHERE` clause by enabling you to filter groups based on aggregate values. While `WHERE` filters rows before aggregation, `HAVING` filters groups after aggregation is complete.
You can use `HAVING` to filter groups where the average exceeds a threshold:
```sql
SELECT
blob1 AS probe_name,
avg(double1) AS average_temp
FROM temperature_readings
GROUP BY probe_name
HAVING average_temp > 10
```
You can also filter groups based on aggregates such as the number of items in the group:
```sql
SELECT
blob1 AS probe_name,
count() AS num_readings
FROM temperature_readings
GROUP BY probe_name
HAVING num_readings > 100
```
## Pattern matching using `LIKE`
The new pattern matching operators enable you to search for strings that match specific patterns using wildcard characters:
- `LIKE` - case-sensitive pattern matching
- `NOT LIKE` - case-sensitive pattern exclusion
- `ILIKE` - case-insensitive pattern matching
- `NOT ILIKE` - case-insensitive pattern exclusion
Pattern matching supports two wildcard characters: `%` (matches zero or more characters) and `_` (matches exactly one character).
You can match strings starting with a prefix:
```sql
SELECT *
FROM logs
WHERE blob1 LIKE 'error%'
```
You can also match file extensions (case-insensitive):
```sql
SELECT *
FROM requests
WHERE blob2 ILIKE '%.jpg'
```
Another example is excluding strings containing specific text:
```sql
SELECT *
FROM events
WHERE blob3 NOT ILIKE '%debug%'
```
## Ready to get started?
Learn more about the [`HAVING` clause](/analytics/analytics-engine/sql-reference/statements/#having-clause) or [pattern matching operators](/analytics/analytics-engine/sql-reference/operators/#pattern-matching-operators) in the Workers Analytics Engine SQL reference documentation.

View file

@ -6,9 +6,10 @@ sidebar:
head:
- tag: title
content: Workers Analytics Engine SQL Reference
---
import { Badge } from "~/components";
The following operators are supported:
## Arithmetic operators
@ -36,6 +37,39 @@ The following operators are supported:
We also support the `BETWEEN` operator for checking a value is in an inclusive range: `a [NOT] BETWEEN b AND c`.
### Pattern matching operators <Badge text="New" variant="tip" size="small" />
| Operator | Description |
| ----------- | -------------------------------------------------------------------------------------------------- |
| `LIKE` | true if the string matches the pattern (case-sensitive)<br/>`column LIKE 'pattern%'` |
| `NOT LIKE` | true if the string does not match the pattern (case-sensitive)<br/>`column NOT LIKE 'pattern%'` |
| `ILIKE` | true if the string matches the pattern (case-insensitive)<br/>`column ILIKE 'pattern%'` |
| `NOT ILIKE` | true if the string does not match the pattern (case-insensitive)<br/>`column NOT ILIKE 'pattern%'` |
Pattern matching supports two wildcard characters:
- `%` matches any sequence of zero or more characters
- `_` matches any single character
Examples:
```sql
-- Match strings starting with "error"
WHERE blob1 LIKE 'error%'
-- Match strings ending with ".jpg" (case-insensitive)
WHERE blob2 ILIKE '%.jpg'
-- Match strings containing "test" anywhere
WHERE blob3 LIKE '%test%'
-- Match exactly 5 characters starting with "log"
WHERE blob4 LIKE 'log__'
-- Exclude strings containing "debug" (case-insensitive)
WHERE blob5 NOT ILIKE '%debug%'
```
## Boolean operators
| Operator | Description |

View file

@ -6,9 +6,10 @@ sidebar:
head:
- tag: title
content: Workers Analytics Engine SQL Reference
---
import { Badge } from "~/components";
## SHOW TABLES statement
`SHOW TABLES` can be used to list the tables on your account. The table name is the name you specified as `dataset` when configuring the workers binding (refer to [Get started with Workers Analytics Engine](/analytics/analytics-engine/get-started/), for more information). The table is automatically created when you write event data in your worker.
@ -49,6 +50,7 @@ SELECT <expression_list>
[FROM <table>|(<subquery>)]
[WHERE <expression>]
[GROUP BY <expression>, ...]
[HAVING <expression>]
[ORDER BY <expression_list>]
[LIMIT <n>|ALL]
[FORMAT <format>]
@ -131,7 +133,7 @@ Note that queries can only operate on a single table. `UNION`, `JOIN` etc. are n
### WHERE clause
`WHERE` is used to filter the rows returned by a query.
`WHERE` is used to filter the rows returned by a query before grouping and aggregation.
Usage:
@ -145,6 +147,8 @@ WHERE <condition>
Expressions containing functions and [operators](/analytics/analytics-engine/sql-reference/operators/#supported-operators) are supported.
To filter results after grouping and aggregation, use the [`HAVING` clause](#having-clause) instead.
Examples:
```sql
@ -186,6 +190,51 @@ GROUP BY probe_name
In the usual case the `<expression>` can just be a column name but it is also possible to supply a complex expression here. Multiple expressions or column names can be supplied separated by commas.
### HAVING clause <Badge text="New" variant="tip" size="small" />
`HAVING` is used to filter the results after grouping and aggregation.
Usage:
```sql
HAVING <condition>
```
`<condition>` can be any expression that evaluates to a boolean, and can reference aggregate functions or grouped columns.
Unlike `WHERE`, which filters rows before grouping, `HAVING` filters groups after aggregation. This allows you to filter based on aggregate values.
[Comparison operators](/analytics/analytics-engine/sql-reference/operators/#comparison-operators) can be used to compare values and [boolean operators](/analytics/analytics-engine/sql-reference/operators/#boolean-operators) can be used to combine conditions.
Examples:
```sql
-- filter groups where the average is greater than 10
SELECT
blob1 AS probe_name,
avg(double1) AS average_temp
FROM temperature_readings
GROUP BY probe_name
HAVING average_temp > 10
-- filter groups with more than 100 readings
SELECT
blob1 AS probe_name,
count() AS num_readings
FROM temperature_readings
GROUP BY probe_name
HAVING num_readings > 100
-- combine multiple conditions
SELECT
blob1 AS city,
avg(double1) AS avg_temp,
count() AS readings
FROM weather_data
GROUP BY city
HAVING avg_temp > 20 AND readings >= 50
```
### ORDER BY clause
`ORDER BY` can be used to control the order in which rows are returned.