ClickHouse: aggregates¶
hare.dialects.clickhouse.functions.aggregates has ClickHouse's own aggregates. They run in
annotate(), aggregate() and Window(...) like hare's, and take _filter= and distinct=True as any
aggregate does.
from hare.dialects.clickhouse.functions.aggregates import ArgMax, Quantile, TopK, Uniq
await PageView.objects.values("day").annotate(visitors=Uniq("visitor_id"))
await Quote.objects.values("symbol").annotate(last_price=ArgMax("price", "quoted_at"))
await PageView.objects.aggregate(typical=Quantile("load_ms", 0.5), slow=Quantile("load_ms", 0.99, exact=True))
await PageView.objects.aggregate(popular=TopK("path", 5))
The aggregates¶
| Aggregate | SQL | Result |
|---|---|---|
Uniq(field) |
uniq |
About how many distinct values a group has — an estimate from a sample of hashes, the fastest |
UniqExact(field) |
uniqExact |
How many distinct values, exactly — every one kept in memory |
UniqCombined(field) |
uniqCombined |
An estimate in less memory and closer than Uniq for many values |
Quantile(field, level=0.5, *, exact=False) |
quantile(level), quantileExact(level) |
The value below which level of the values lie — an interpolated estimate, or with exact=True one of the values |
Quantiles(field, *levels, exact=False) |
quantiles(...), quantilesExact(...) |
Several quantiles in one pass, an array in the order of the levels |
Median(field, *, exact=False) |
quantile(0.5) |
The median — an estimate, or the middle value with exact=True |
ArgMin(field, by), ArgMax(field, by) |
argMin, argMax |
The value of field in the row of the group where by is the least or the greatest |
GroupArray(field, *, max_size=None) |
groupArray |
The values as an array in the order read, NULL left out; max_size keeps the first that many |
GroupUniqArray(field, *, max_size=None) |
groupUniqArray |
The distinct values as an array, in no order; max_size keeps that many of them |
TopK(field, k=10) |
topK(k) |
About the k most frequent values, the most frequent first — exact only for few distinct values |
AnyValue(field), AnyLast(field) |
any, anyLast |
The first or the last value ClickHouse meets in the group, whichever it is |
SumMap(field) |
sumMap |
The maps of a MapField added up key by key |
Quantiles, GroupArray, GroupUniqArray and TopK give a list; SumMap a dict. Uniq, Quantile
and TopK are estimates and may differ between runs over many rows — UniqExact and exact=True are
deterministic.
_filter, distinct and empty groups¶
_filter=Q(...)is writtenFILTER (WHERE ...)anddistinct=TrueasDISTINCTinside the call, as on other databases — ClickHouse runs them as its-Ifand-Distinctcombinators.- Over no rows
Max,Min,Avg,StdDevandVariancegiveNone, as do the aggregates below: each is written by its-OrNullform (maxOrNull(amount)) — the list is inNULLfrom an aggregate over no rows.Sumgives ClickHouse's own0(0.00for a decimal;Nonefor a nullable field, and over onlyNULLvalues too). In a grouped statement, whose groups hold at least one row, an aggregate without_filterkeeps its plain, cheaper form. A sample deviation or variance over one value isNone, not ClickHouse's NaN. - Over no rows (or only
NULLvalues)Quantile,Median,ArgMin,ArgMax,AnyValueandAnyLastgiveNone;Uniq/UniqExactgive0(UniqCombinedof a nullable field givesNone— ClickHouse's ownuniqCombined),GroupArray,GroupUniqArrayandTopKan empty list, andQuantilesaNaNfor each level — ClickHouse holds noNULLinside an array; withexact=Trueover an integer field a0for each level (ClickHouse's ownquantilesExact). ArgMin/ArgMaxread only the rows whosefieldisn'tNULL: the value of the row with the least/greatestbyamong them, notNonewhen the row with the extremebyholdsNULL.ArrayAggof hare isgroupArrayof a tuple holding each value — every value is an element of hare'sArrayAgg,NULLtoo, which a plaingroupArrayleaves out; withdistinct=Trueit isgroupUniqArray, and itsorder_bysorts the array — aNULLordering value where hare's ordering puts it (last going up, first going down), all orderings going one way (up or down; both raiseUnSupportedError).