Querying: the ClickHouse dialect

ClickHouse · Essentials · 12 min

The built-in functions turn multi-step SQL into one fast, readable query.

Standard SQL works, but ClickHouse adds a lot that analytics queries lean on.

  • Conditional aggregates: countIf(status = 'error'), sumIf(amount, country = 'DE'), avgIf.
  • Approximate and exact distinct counts: uniq(user_id) is fast and approximate (error typically well under 1%); uniqExact is exact but uses more memory. count(DISTINCT x) maps to uniqExact by default.
  • Time bucketing: toStartOfHour(ts), toStartOfDay, toStartOfInterval(ts, INTERVAL 15 minute), toYYYYMM(ts), toDayOfWeek.
  • argMax(price, ts): the price at the latest ts, without a join or window.
  • LIMIT n BY col: top n rows per group, e.g. the 3 slowest pages per day.
  • WITH TOTALS adds a grand-total row to a GROUP BY.
  • count() needs no argument, and you can reuse an alias anywhere in the same SELECT, even in WHERE.

Functions are case-sensitive in their camelCase form (toStartOfHour), although common SQL ones like COUNT and SUM also accept any case. Also note that integer division / returns a Float64; use intDiv(a, b) for integer division.

Example

SELECT
    toStartOfDay(ts)                 AS day,
    count()                          AS hits,
    countIf(ms > 500)                AS slow,
    round(slow / hits * 100, 1)      AS slow_pct,   -- aliases are reusable
    uniq(url)                        AS pages
FROM page_views
WHERE ts >= now() - INTERVAL 7 DAY
GROUP BY day WITH TOTALS          -- extra grand-total row
ORDER BY day;

-- 2 slowest pages per day (top-N per group without a window function)
SELECT toDate(ts) AS day, url, max(ms) AS worst
FROM page_views
GROUP BY day, url
ORDER BY day, worst DESC
LIMIT 2 BY day;

Remember

  • countIf / sumIf replace CASE inside aggregates
  • uniq is fast approximate distinct; uniqExact is exact
  • toStartOf* functions bucket time; LIMIT n BY gives top-N per group

Watch out for

  • Expecting 7 / 2 to be 3: ClickHouse returns 3.5; use intDiv for integer division.

Check yourself

  1. What does LIMIT 3 BY country return?
  2. Which is the cheapest way to estimate distinct users over billions of rows?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: clickhouse.com/docs/sql-reference/aggregate-functions/reference