From 954af868b2733c9db7ade9ba0e207d7f8cce2b71 Mon Sep 17 00:00:00 2001 From: Charlie Dowler Date: Mon, 9 Feb 2026 17:56:12 +0000 Subject: [PATCH 1/2] Add documentation for table calculation functions Document the 8 new table calculation functions from Lightdash PRs #19999 and #20102: row, offset, index, lookup, offset_list, list, pivot_row, and pivot_offset_list. Each function page includes signature, parameter table, practical example, and compiled SQL in an accordion. Co-Authored-By: Claude Opus 4.6 --- docs.json | 7 + guides/table-calculations.mdx | 17 +- guides/table-calculations/sql-templates.mdx | 4 + .../pivot-functions.mdx | 92 ++++++++ .../row-functions.mdx | 208 ++++++++++++++++++ 5 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 references/table-calculation-functions/pivot-functions.mdx create mode 100644 references/table-calculation-functions/row-functions.mdx diff --git a/docs.json b/docs.json index 2cb4d473..5fe15638 100644 --- a/docs.json +++ b/docs.json @@ -86,6 +86,13 @@ "guides/how-to-promote-content", "guides/keyboard-shortcuts", "guides/table-calculations", + { + "group": "Table calculation functions", + "pages": [ + "references/table-calculation-functions/row-functions", + "references/table-calculation-functions/pivot-functions" + ] + }, { "group": "Table calc SQL templates", "pages": [ diff --git a/guides/table-calculations.mdx b/guides/table-calculations.mdx index d154f96c..8e2824a2 100644 --- a/guides/table-calculations.mdx +++ b/guides/table-calculations.mdx @@ -53,7 +53,7 @@ Once you've got some data in your results table, you can create a table calculat ##### Write the SQL for your table calculation in the pop-up box -Your table calculation is defined using raw SQL that you write up in this pop up box. If you're not sure what to write here, you can [check out some of our table calculation SQL templates](#table-calculation-sql-templates). +Your table calculation is defined using raw SQL that you write up in this pop up box. If you're not sure what to write here, you can [check out some of our table calculation SQL templates](#table-calculation-functions-and-sql-templates). To reference the metrics and dimensions in your results table, you can either use the autocomplete, or you can manually write the full field name using the format `${table_name.field_name}`. @@ -62,6 +62,15 @@ To reference the metrics and dimensions in your results table, you can either us +### Using table calculation functions + +In addition to writing raw SQL, you can use built-in functions that simplify common table calculation patterns: + +- **[Row functions](/references/table-calculation-functions/row-functions)** — Access values from other rows (e.g., previous row, specific row number, lookups) +- **[Pivot functions](/references/table-calculation-functions/pivot-functions)** — Access values across pivot columns + +These functions compile to SQL window functions automatically, so you don't need to write `LAG`, `LEAD`, or `ROW_NUMBER` by hand. + ##### Update the format of your table calculation (if needed) If needed, you can update the format of your table calculation to things like percent formatting using the `format` tab. @@ -105,8 +114,8 @@ For example: You use table calculations to calculate the `percentage_of_shipping ![](/images/guides/table-calculations/table_calculation_filter_example.jpg) -## Table calculation SQL templates +## Table calculation functions and SQL templates -I'm not sure about you, but I definitely rely on copy-pasting old SQL code to write 90% of my new SQL queries. So, we thought it might be useful to give you some snippets of SQL code to help you get started with your most common table calculations. +If you prefer not to write raw SQL, check out the built-in [row functions](/references/table-calculation-functions/row-functions) and [pivot functions](/references/table-calculation-functions/pivot-functions) — they handle common patterns like accessing previous rows, row numbering, and working across pivot columns. -You can check out our table calculation SQL templates [here](/guides/table-calculations/sql-templates). +For more advanced or custom SQL, we also have copy-paste SQL templates to help you get started with common table calculations. You can check out our table calculation SQL templates [here](/guides/table-calculations/sql-templates). diff --git a/guides/table-calculations/sql-templates.mdx b/guides/table-calculations/sql-templates.mdx index a52de417..6ab97f1e 100644 --- a/guides/table-calculations/sql-templates.mdx +++ b/guides/table-calculations/sql-templates.mdx @@ -5,5 +5,9 @@ mode: wide sidebarTitle: Overview --- + +Looking for a simpler alternative to raw SQL? Check out the built-in [row functions](/references/table-calculation-functions/row-functions) and [pivot functions](/references/table-calculation-functions/pivot-functions) — they handle common patterns like accessing previous rows and working across pivot columns without needing to write window function SQL. + + diff --git a/references/table-calculation-functions/pivot-functions.mdx b/references/table-calculation-functions/pivot-functions.mdx new file mode 100644 index 00000000..5cecde2b --- /dev/null +++ b/references/table-calculation-functions/pivot-functions.mdx @@ -0,0 +1,92 @@ +--- +title: "Pivot functions" +description: "Built-in functions for accessing values across pivot columns in your table calculations." +--- + +Pivot functions let you work with values across pivot columns in your results table. When you pivot a dimension in Lightdash, the values of that dimension become separate columns — pivot functions give you a way to reference and aggregate across those columns. + + +Pivot functions are only available when your query includes a pivoted dimension. + + +## pivot_row + +Returns an array of all values across the pivot columns for the current row. + +``` +pivot_row(expression) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `expression` | column reference or SQL expression | The expression to evaluate for each pivot column | + +**Example** + +Get all pivoted revenue values for the current row: + +``` +pivot_row(${orders.total_revenue}) +``` + + +```sql +ARRAY_AGG(${orders.total_revenue}) OVER ( + PARTITION BY "row_index" + ORDER BY "column_index" + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING +) +``` + + +--- + +## pivot_offset_list + +Returns an array of values from consecutive pivot columns starting at a relative offset from the current column. + +``` +pivot_offset_list(expression, columnOffset, numValues) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `expression` | column reference or SQL expression | The expression to evaluate | +| `columnOffset` | integer | Starting column offset. Negative = previous columns, positive = next columns, 0 = current column | +| `numValues` | integer | Number of consecutive pivot columns to include | + +Values are returned as `NULL` when the offset points to a non-adjacent pivot column (e.g., if columns were filtered out). + +**Example** + +Get the current and two previous pivot column values: + +``` +pivot_offset_list(${orders.total_revenue}, -2, 3) +``` + + +```sql +ARRAY[ + CASE WHEN LAG("column_index", 2) OVER ( + PARTITION BY "row_index" ORDER BY "column_index" + ) = "column_index" + (-2) + THEN LAG(${orders.total_revenue}, 2) OVER ( + PARTITION BY "row_index" ORDER BY "column_index" + ) + ELSE NULL + END, + CASE WHEN LAG("column_index", 1) OVER ( + PARTITION BY "row_index" ORDER BY "column_index" + ) = "column_index" + (-1) + THEN LAG(${orders.total_revenue}, 1) OVER ( + PARTITION BY "row_index" ORDER BY "column_index" + ) + ELSE NULL + END, + ${orders.total_revenue} +] +``` + +Each element includes an adjacency guard — a `CASE WHEN` check that verifies the target column is actually adjacent. This prevents incorrect values when pivot columns have been filtered out and are non-contiguous. + diff --git a/references/table-calculation-functions/row-functions.mdx b/references/table-calculation-functions/row-functions.mdx new file mode 100644 index 00000000..e785441a --- /dev/null +++ b/references/table-calculation-functions/row-functions.mdx @@ -0,0 +1,208 @@ +--- +title: "Row functions" +description: "Built-in functions for accessing values from other rows in your table calculations." +--- + +Row functions let you reference values from other rows without writing raw SQL window functions. They use the `${table.column}` syntax to reference fields in your results table. + + +Row functions use your query's current sort order to determine row positions. Changing the sort order of your results will change the output of these functions. + + +## row + +Returns the 1-based row number of the current row. + +``` +row() +``` + +**Parameters:** None + +**Example** + +Add a row number column to your results: + +``` +row() +``` + + +```sql +ROW_NUMBER() OVER (ORDER BY ...) +``` + +The `ORDER BY` clause uses the sort order configured in your query. + + +--- + +## offset + +Returns the value of a column from a row at a relative offset from the current row. + +``` +offset(column, rowOffset) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `column` | column reference | The column to get the value from | +| `rowOffset` | integer | Number of rows to offset. Negative = previous rows, positive = next rows, 0 = current row | + +**Example** + +Get the previous row's revenue to calculate period-over-period changes: + +``` +${orders.total_revenue} - offset(${orders.total_revenue}, -1) +``` + + +For negative offsets (previous rows): +```sql +LAG(${orders.total_revenue}, 1) OVER (ORDER BY ...) +``` + +For positive offsets (next rows): +```sql +LEAD(${orders.total_revenue}, 1) OVER (ORDER BY ...) +``` + +For an offset of 0, the column value is returned directly with no window function. + + +--- + +## index + +Returns the value of an expression from an absolute row position (1-based). + +``` +index(expression, rowIndex) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `expression` | column reference or SQL expression | The expression to evaluate | +| `rowIndex` | integer (≥ 1) | The 1-based row position to get the value from | + +**Example** + +Compare every row's revenue against the first row's revenue: + +``` +${orders.total_revenue} / index(${orders.total_revenue}, 1) +``` + + +```sql +NTH_VALUE(${orders.total_revenue}, 1) OVER ( + ORDER BY ... + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING +) +``` + + +--- + +## lookup + +Finds a value in one column and returns the corresponding value from another column. + +``` +lookup(value, lookupColumn, resultColumn) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `value` | any | The value to search for | +| `lookupColumn` | column reference | The column to search in | +| `resultColumn` | column reference | The column to return the value from | + +If multiple rows match, the largest matching value from `resultColumn` is returned. + +**Example** + +Look up the revenue for a specific status: + +``` +lookup('completed', ${orders.status}, ${orders.total_revenue}) +``` + + +```sql +MAX( + CASE WHEN ${orders.status} = 'completed' + THEN ${orders.total_revenue} + ELSE NULL + END +) OVER () +``` + + +--- + +## offset_list + +Returns an array of values from consecutive rows starting at a relative offset. + +``` +offset_list(column, rowOffset, numValues) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `column` | column reference | The column to get values from | +| `rowOffset` | integer | Starting row offset. Negative = previous rows, positive = next rows, 0 = current row | +| `numValues` | integer | Number of consecutive values to include | + +**Example** + +Get the current and two previous revenue values (a 3-period window): + +``` +offset_list(${orders.total_revenue}, -2, 3) +``` + + +```sql +ARRAY[ + LAG(${orders.total_revenue}, 2) OVER (ORDER BY ...), + LAG(${orders.total_revenue}, 1) OVER (ORDER BY ...), + ${orders.total_revenue} +] +``` + + +--- + +## list + +Constructs an array from multiple values. Unlike the other row functions, `list` does not use any windowing. + +``` +list(value1, value2, ..., valueN) +``` + +| Parameter | Type | Description | +| :--- | :--- | :--- | +| `value1...valueN` | any | Values or expressions to combine into an array | + +**Example** + +Create an array of specific column values: + +``` +list(${orders.total_revenue}, ${orders.total_cost}, ${orders.total_profit}) +``` + + +```sql +ARRAY[ + ${orders.total_revenue}, + ${orders.total_cost}, + ${orders.total_profit} +] +``` + From b0480c1573817d3efa31b13816a80980df6ed096 Mon Sep 17 00:00:00 2001 From: Charlie Dowler Date: Mon, 9 Feb 2026 19:23:51 +0000 Subject: [PATCH 2/2] Add experimental banner to table calculation function pages Co-Authored-By: Claude Opus 4.6 --- references/table-calculation-functions/pivot-functions.mdx | 6 ++++++ references/table-calculation-functions/row-functions.mdx | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/references/table-calculation-functions/pivot-functions.mdx b/references/table-calculation-functions/pivot-functions.mdx index 5cecde2b..85314d44 100644 --- a/references/table-calculation-functions/pivot-functions.mdx +++ b/references/table-calculation-functions/pivot-functions.mdx @@ -3,6 +3,12 @@ title: "Pivot functions" description: "Built-in functions for accessing values across pivot columns in your table calculations." --- + + **Table calculation functions are an Experimental feature.** + + These functions may change or be updated without notice as we iterate. See [feature maturity levels](/references/workspace/feature-maturity-levels) for details. + + Pivot functions let you work with values across pivot columns in your results table. When you pivot a dimension in Lightdash, the values of that dimension become separate columns — pivot functions give you a way to reference and aggregate across those columns. diff --git a/references/table-calculation-functions/row-functions.mdx b/references/table-calculation-functions/row-functions.mdx index e785441a..ac461285 100644 --- a/references/table-calculation-functions/row-functions.mdx +++ b/references/table-calculation-functions/row-functions.mdx @@ -3,6 +3,12 @@ title: "Row functions" description: "Built-in functions for accessing values from other rows in your table calculations." --- + + **Table calculation functions are an Experimental feature.** + + These functions may change or be updated without notice as we iterate. See [feature maturity levels](/references/workspace/feature-maturity-levels) for details. + + Row functions let you reference values from other rows without writing raw SQL window functions. They use the `${table.column}` syntax to reference fields in your results table.