YTD
Time intelligence
YTD(expr, dateCol)
Accumulates expr from the start of the year through each date bucket (a window SUM partitioned by year). The operand must be additive — a linear combination of Sum/Count aggregates (measure references included; Avg is admitted via sum/count decomposition). Anything else fails with SQX015.
When to use it
Section titled “When to use it”- Year-to-date KPI cards and pacing lines — where are we against the year so far?
- YTD-vs-prior-YTD comparisons: pair with
Calculate(…, DateShift(…))as in the example.
Example
Section titled “Example”RevenueYTD := YTD([Revenue], Date.Date)
// Ratios: accumulate the parts, then divideAOVYTD := Divide(YTD([Revenue]), YTD([Orders]))
// Prior-year YTD: wrap in Calculate + DateShift — last year's accumulation// lands on this year's buckets, ready for YTD-vs-YTD comparisonsRevenueYTDLY := Calculate([RevenueYTD], DateShift(Date.Date, -1, "year"))YTD([AvgOrderValue]) is rejected — a running sum of per-bucket ratios is silently wrong.
Under the hood
Section titled “Under the hood”No self-join needed — the accumulation is a nested-aggregate window over the chart’s own buckets:
// On a line chart by month, split by regionRevenueYTD := YTD([Revenue], Date.Date)SELECT "Sales"."region", DATE_TRUNC('month', "Sales"."sold_at") AS "month", SUM(SUM("Sales"."amount")) OVER ( PARTITION BY "Sales"."region", DATE_TRUNC('year', DATE_TRUNC('month', "Sales"."sold_at")) ORDER BY DATE_TRUNC('month', "Sales"."sold_at") ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS "RevenueYTD"FROM "sales" AS "Sales"GROUP BY "Sales"."region", DATE_TRUNC('month', "Sales"."sold_at")The window partitions by the other grouping keys plus the year of the bucketed axis, so each region accumulates independently and resets each January. Missing months simply contribute nothing.