ClickHouse Time Series

Typed time-series queries on ClickHouse in TypeScript

Time-series queries are the most common ClickHouse use case and the most common source of subtle TypeScript bugs — because ClickHouse DateTime columns return as strings and ClickHouse date functions are specific to ClickHouse SQL. hypequery gives TypeScript teams a composable, type-safe path to time-series analytics.

Date functions

toStartOfDay, toStartOfHour, toStartOfWeek

DateTime mapping

DateTime → string (not Date)

Best for

Time-series dashboards and trend analysis

ClickHouse date functions are ClickHouse-specific — generic query builders miss them

Time-series queries in ClickHouse live or die on date bucketing. toStartOfDay, toStartOfHour, and toStartOfWeek are central to the workload, and a TypeScript layer needs to make those patterns readable instead of burying them in repetitive string fragments.

DateTime columns return as strings — TypeScript that expects Date objects breaks silently

ClickHouse DateTime columns are returned as strings over the HTTP interface. TypeScript code that assigns them to Date properties or passes them to functions expecting Date objects compiles fine but behaves incorrectly at runtime. Schema-generated types map DateTime to string explicitly, making the correct handling visible.

Reusable time-range filters get duplicated across every time-series query

Last 7 days, last 30 days, custom range — every chart in a time-series dashboard needs the same time-range logic. Without a shared, composable pattern, the date arithmetic is copy-pasted across every query and endpoint, making changes fragile.

Time-series query pattern

toStartOfDay groupBy with schema-generated DateTime string types

The foundation of correct time-series queries in TypeScript on ClickHouse is understanding the DateTime → string mapping and using it intentionally. Schema generation makes this explicit at the type level rather than leaving it as a runtime discovery.

  • Generate schema types — DateTime columns appear as string in the emitted TypeScript
  • Use toStartOfDay(created_at) as day in .select() for daily bucketing
  • GroupBy the alias (day) not the expression to avoid repetition
  • UInt64 aggregates (count, sum) also return as string — parse at the chart layer with parseInt or parseFloat
  • Parse ClickHouse DateTime strings explicitly in the chart layer and be deliberate about timezone handling

Time-series query

Daily metrics query with toStartOfDay and typed DateTime strings

time-series-query-pattern.ts

The return type comment makes the string nature of all numeric and date fields explicit. This is what schema generation emits — and what the chart layer must handle correctly.

Reusable time-range pattern

Configurable granularity and preset time ranges without query duplication

A reusable time-series query accepts granularity (minute/hour/day/week) and either a preset range or explicit start/end dates. This single definition replaces the per-chart date logic that typically gets duplicated across dashboards.

The granularityFn map keeps the ClickHouse-specific function names in one place. If the available granularities change, the map is the only thing that needs updating — not every query that uses date bucketing.

Preset time ranges are pre-computed in TypeScript before being passed to ClickHouse. This is simpler than using ClickHouse NOW() minus interval expressions, which are harder to type and test.

Reusable time-series API

One query definition for all granularities and time-range presets

reusable-time-range-pattern.ts

The query handles minute, hour, day, and week granularity through a single parameter. Adding a new granularity means adding one entry to granularityFn — not a new query.

Why teams search for this

Common implementation questions this page should solve

ClickHouse time series TypeScript

Time-series work gets messy when every chart reimplements date parsing, bucketing, and range logic. A reusable query pattern is more valuable than a one-off date helper.

ClickHouse toStartOfDay TypeScript

toStartOfDay is usually the first useful bucket, but the real pattern is keeping the bucketing expression readable and grouping by the alias instead of repeating the function call.

ClickHouse DateTime TypeScript

ClickHouse DateTime values arrive as strings over HTTP. If that stays implicit, chart code quietly treats them like Date objects and bugs slip through.

ClickHouse date groupBy TypeScript

GroupBy on a date function expression works best when the expression is aliased in SELECT and the alias is used in GROUP BY. hypequery .groupBy() accepts the alias string, keeping queries readable.

Next step

Generate your schema and write a typed toStartOfDay time-series query

Schema generation captures the DateTime → string mapping for your tables. Once that is in place, a daily metrics query with toStartOfDay groupBy follows the pattern above and is immediately usable in a chart component.