Skip to content

Commit 954af86

Browse files
charliedowlerclaude
andcommitted
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 <noreply@anthropic.com>
1 parent acd62f0 commit 954af86

5 files changed

Lines changed: 324 additions & 4 deletions

File tree

docs.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@
8686
"guides/how-to-promote-content",
8787
"guides/keyboard-shortcuts",
8888
"guides/table-calculations",
89+
{
90+
"group": "Table calculation functions",
91+
"pages": [
92+
"references/table-calculation-functions/row-functions",
93+
"references/table-calculation-functions/pivot-functions"
94+
]
95+
},
8996
{
9097
"group": "Table calc SQL templates",
9198
"pages": [

guides/table-calculations.mdx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Once you've got some data in your results table, you can create a table calculat
5353

5454
##### Write the SQL for your table calculation in the pop-up box
5555

56-
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).
56+
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).
5757

5858
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}`.
5959

@@ -62,6 +62,15 @@ To reference the metrics and dimensions in your results table, you can either us
6262
</Frame>
6363

6464

65+
### Using table calculation functions
66+
67+
In addition to writing raw SQL, you can use built-in functions that simplify common table calculation patterns:
68+
69+
- **[Row functions](/references/table-calculation-functions/row-functions)** — Access values from other rows (e.g., previous row, specific row number, lookups)
70+
- **[Pivot functions](/references/table-calculation-functions/pivot-functions)** — Access values across pivot columns
71+
72+
These functions compile to SQL window functions automatically, so you don't need to write `LAG`, `LEAD`, or `ROW_NUMBER` by hand.
73+
6574
##### Update the format of your table calculation (if needed)
6675

6776
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
105114
![](/images/guides/table-calculations/table_calculation_filter_example.jpg)
106115
</Frame>
107116

108-
## Table calculation SQL templates
117+
## Table calculation functions and SQL templates
109118

110-
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.
119+
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.
111120

112-
You can check out our table calculation SQL templates [here](/guides/table-calculations/sql-templates).
121+
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).

guides/table-calculations/sql-templates.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ mode: wide
55
sidebarTitle: Overview
66
---
77

8+
<Tip>
9+
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.
10+
</Tip>
11+
812
<CardGroup cols={2} > <Card title="Percent change from previous" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/percent-change-from-previous"iconType="solid" horizontal /> <Card title="Percent of previous value" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/percent-of-previous-value" iconType="solid" horizontal/> <Card title="Percent of column total" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/percent-of-total-column"iconType="solid" horizontal /> <Card title="Percent of group/pivot total" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/percent-of-group-pivot-total" iconType="solid" horizontal/> <Card title="Rank in column" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/rank-in-column" iconType="solid" horizontal/> <Card title="Running total" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/running-total" iconType="solid" horizontal/> <Card title="Rolling window" icon="file-lines" href="/guides/table-calculations/table-calculation-sql-templates/rolling-window"iconType="solid" horizontal /> </CardGroup>
913

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
title: "Pivot functions"
3+
description: "Built-in functions for accessing values across pivot columns in your table calculations."
4+
---
5+
6+
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.
7+
8+
<Note>
9+
Pivot functions are only available when your query includes a pivoted dimension.
10+
</Note>
11+
12+
## pivot_row
13+
14+
Returns an array of all values across the pivot columns for the current row.
15+
16+
```
17+
pivot_row(expression)
18+
```
19+
20+
| Parameter | Type | Description |
21+
| :--- | :--- | :--- |
22+
| `expression` | column reference or SQL expression | The expression to evaluate for each pivot column |
23+
24+
**Example**
25+
26+
Get all pivoted revenue values for the current row:
27+
28+
```
29+
pivot_row(${orders.total_revenue})
30+
```
31+
32+
<Accordion title="Compiled SQL">
33+
```sql
34+
ARRAY_AGG(${orders.total_revenue}) OVER (
35+
PARTITION BY "row_index"
36+
ORDER BY "column_index"
37+
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
38+
)
39+
```
40+
</Accordion>
41+
42+
---
43+
44+
## pivot_offset_list
45+
46+
Returns an array of values from consecutive pivot columns starting at a relative offset from the current column.
47+
48+
```
49+
pivot_offset_list(expression, columnOffset, numValues)
50+
```
51+
52+
| Parameter | Type | Description |
53+
| :--- | :--- | :--- |
54+
| `expression` | column reference or SQL expression | The expression to evaluate |
55+
| `columnOffset` | integer | Starting column offset. Negative = previous columns, positive = next columns, 0 = current column |
56+
| `numValues` | integer | Number of consecutive pivot columns to include |
57+
58+
Values are returned as `NULL` when the offset points to a non-adjacent pivot column (e.g., if columns were filtered out).
59+
60+
**Example**
61+
62+
Get the current and two previous pivot column values:
63+
64+
```
65+
pivot_offset_list(${orders.total_revenue}, -2, 3)
66+
```
67+
68+
<Accordion title="Compiled SQL">
69+
```sql
70+
ARRAY[
71+
CASE WHEN LAG("column_index", 2) OVER (
72+
PARTITION BY "row_index" ORDER BY "column_index"
73+
) = "column_index" + (-2)
74+
THEN LAG(${orders.total_revenue}, 2) OVER (
75+
PARTITION BY "row_index" ORDER BY "column_index"
76+
)
77+
ELSE NULL
78+
END,
79+
CASE WHEN LAG("column_index", 1) OVER (
80+
PARTITION BY "row_index" ORDER BY "column_index"
81+
) = "column_index" + (-1)
82+
THEN LAG(${orders.total_revenue}, 1) OVER (
83+
PARTITION BY "row_index" ORDER BY "column_index"
84+
)
85+
ELSE NULL
86+
END,
87+
${orders.total_revenue}
88+
]
89+
```
90+
91+
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.
92+
</Accordion>
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
title: "Row functions"
3+
description: "Built-in functions for accessing values from other rows in your table calculations."
4+
---
5+
6+
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.
7+
8+
<Note>
9+
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.
10+
</Note>
11+
12+
## row
13+
14+
Returns the 1-based row number of the current row.
15+
16+
```
17+
row()
18+
```
19+
20+
**Parameters:** None
21+
22+
**Example**
23+
24+
Add a row number column to your results:
25+
26+
```
27+
row()
28+
```
29+
30+
<Accordion title="Compiled SQL">
31+
```sql
32+
ROW_NUMBER() OVER (ORDER BY ...)
33+
```
34+
35+
The `ORDER BY` clause uses the sort order configured in your query.
36+
</Accordion>
37+
38+
---
39+
40+
## offset
41+
42+
Returns the value of a column from a row at a relative offset from the current row.
43+
44+
```
45+
offset(column, rowOffset)
46+
```
47+
48+
| Parameter | Type | Description |
49+
| :--- | :--- | :--- |
50+
| `column` | column reference | The column to get the value from |
51+
| `rowOffset` | integer | Number of rows to offset. Negative = previous rows, positive = next rows, 0 = current row |
52+
53+
**Example**
54+
55+
Get the previous row's revenue to calculate period-over-period changes:
56+
57+
```
58+
${orders.total_revenue} - offset(${orders.total_revenue}, -1)
59+
```
60+
61+
<Accordion title="Compiled SQL">
62+
For negative offsets (previous rows):
63+
```sql
64+
LAG(${orders.total_revenue}, 1) OVER (ORDER BY ...)
65+
```
66+
67+
For positive offsets (next rows):
68+
```sql
69+
LEAD(${orders.total_revenue}, 1) OVER (ORDER BY ...)
70+
```
71+
72+
For an offset of 0, the column value is returned directly with no window function.
73+
</Accordion>
74+
75+
---
76+
77+
## index
78+
79+
Returns the value of an expression from an absolute row position (1-based).
80+
81+
```
82+
index(expression, rowIndex)
83+
```
84+
85+
| Parameter | Type | Description |
86+
| :--- | :--- | :--- |
87+
| `expression` | column reference or SQL expression | The expression to evaluate |
88+
| `rowIndex` | integer (≥ 1) | The 1-based row position to get the value from |
89+
90+
**Example**
91+
92+
Compare every row's revenue against the first row's revenue:
93+
94+
```
95+
${orders.total_revenue} / index(${orders.total_revenue}, 1)
96+
```
97+
98+
<Accordion title="Compiled SQL">
99+
```sql
100+
NTH_VALUE(${orders.total_revenue}, 1) OVER (
101+
ORDER BY ...
102+
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
103+
)
104+
```
105+
</Accordion>
106+
107+
---
108+
109+
## lookup
110+
111+
Finds a value in one column and returns the corresponding value from another column.
112+
113+
```
114+
lookup(value, lookupColumn, resultColumn)
115+
```
116+
117+
| Parameter | Type | Description |
118+
| :--- | :--- | :--- |
119+
| `value` | any | The value to search for |
120+
| `lookupColumn` | column reference | The column to search in |
121+
| `resultColumn` | column reference | The column to return the value from |
122+
123+
If multiple rows match, the largest matching value from `resultColumn` is returned.
124+
125+
**Example**
126+
127+
Look up the revenue for a specific status:
128+
129+
```
130+
lookup('completed', ${orders.status}, ${orders.total_revenue})
131+
```
132+
133+
<Accordion title="Compiled SQL">
134+
```sql
135+
MAX(
136+
CASE WHEN ${orders.status} = 'completed'
137+
THEN ${orders.total_revenue}
138+
ELSE NULL
139+
END
140+
) OVER ()
141+
```
142+
</Accordion>
143+
144+
---
145+
146+
## offset_list
147+
148+
Returns an array of values from consecutive rows starting at a relative offset.
149+
150+
```
151+
offset_list(column, rowOffset, numValues)
152+
```
153+
154+
| Parameter | Type | Description |
155+
| :--- | :--- | :--- |
156+
| `column` | column reference | The column to get values from |
157+
| `rowOffset` | integer | Starting row offset. Negative = previous rows, positive = next rows, 0 = current row |
158+
| `numValues` | integer | Number of consecutive values to include |
159+
160+
**Example**
161+
162+
Get the current and two previous revenue values (a 3-period window):
163+
164+
```
165+
offset_list(${orders.total_revenue}, -2, 3)
166+
```
167+
168+
<Accordion title="Compiled SQL">
169+
```sql
170+
ARRAY[
171+
LAG(${orders.total_revenue}, 2) OVER (ORDER BY ...),
172+
LAG(${orders.total_revenue}, 1) OVER (ORDER BY ...),
173+
${orders.total_revenue}
174+
]
175+
```
176+
</Accordion>
177+
178+
---
179+
180+
## list
181+
182+
Constructs an array from multiple values. Unlike the other row functions, `list` does not use any windowing.
183+
184+
```
185+
list(value1, value2, ..., valueN)
186+
```
187+
188+
| Parameter | Type | Description |
189+
| :--- | :--- | :--- |
190+
| `value1...valueN` | any | Values or expressions to combine into an array |
191+
192+
**Example**
193+
194+
Create an array of specific column values:
195+
196+
```
197+
list(${orders.total_revenue}, ${orders.total_cost}, ${orders.total_profit})
198+
```
199+
200+
<Accordion title="Compiled SQL">
201+
```sql
202+
ARRAY[
203+
${orders.total_revenue},
204+
${orders.total_cost},
205+
${orders.total_profit}
206+
]
207+
```
208+
</Accordion>

0 commit comments

Comments
 (0)