Skip to main content
Clauses and query constructs you can use to shape a segment query. Every segment query must return a distinct_id column.

WHERE / ORDER BY / LIMIT / OFFSET

The core row-shaping clauses. WHERE filters rows before grouping, ORDER BY sorts the result, LIMIT caps the number of rows returned, and OFFSET skips a number of leading rows (useful with ORDER BY for paging). Syntax
Example
Most recent purchasers in the last 30 days

GROUP BY … HAVING

Aggregates rows into groups and then filters those groups with a HAVING condition. Unlike WHERE, HAVING can reference aggregate results such as count(*). Syntax
Example
Users with more than three failed payments

IN (subquery)

Keeps rows whose value appears in the result of a subquery. A common way to include users who match a condition captured in another table. Syntax
Example
Users who have triggered a purchase

JOIN / LEFT JOIN

Combines rows from two tables on a join condition. A plain (inner) JOIN keeps only matching rows; a LEFT JOIN keeps every row from the left table and fills unmatched right-side columns with NULL, which is useful for building anti-joins. Syntax
Example
Pro-plan users who opened the app (inner join)
Users who never made a purchase (left-join anti-join)

Derived table (subquery in FROM)

A subquery placed in the FROM clause and given an alias, so you can filter or aggregate over its result as if it were a table. Syntax
Example
Users with at least ten logins

CTE (WITH … AS)

A common table expression defines a named, temporary result set that you can reference later in the same query. Use it to break a complex segment into readable, composable steps. Syntax
Example
Users with more than five purchases

DISTINCT

Removes duplicate rows from the result set, returning each unique combination of the selected columns once. Syntax
Example
Unique users who opened the app

UNION / UNION ALL

Combines the rows of two or more queries with matching columns. UNION removes duplicate rows (it is treated as UNION DISTINCT on ClickHouse), while UNION ALL keeps every row, including duplicates. Syntax
Example
Users who purchased or started a subscription

DISTINCT ON

Returns the first row for each distinct value of the given expressions. Pair it with ORDER BY to control which row is kept per group (for example, the most recent event per user). Syntax
Example
One row per user, keyed to their latest event

GROUP BY CUBE

Produces grouping sets for every combination of the listed expressions, including subtotal rows where a grouped expression is rolled up to NULL. Filter with HAVING to keep only the rows you want in the segment. Syntax
Example
Users grouped across page dimensions, keeping per-user rows

GROUP BY ROLLUP

Produces grouping sets in a hierarchy from most to least detailed, adding subtotal rows as each trailing expression is rolled up to NULL. Filter with HAVING to keep only the rows you want in the segment. Syntax
Example
Users grouped by purchase category, keeping per-user rows

EXISTS (correlated subquery)

Tests whether a correlated subquery returns at least one row, letting you keep users who have a related event. The subquery references the outer query, so it is evaluated per outer row (PostgreSQL only). Syntax
Example
Users who have at least one purchase

NOT EXISTS

The negation of EXISTS: keeps users for whom the correlated subquery returns no rows. Ideal for exclusion segments such as users who never performed an action (PostgreSQL only). Syntax
Example
Users who have never made a purchase