Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
17 changes: 13 additions & 4 deletions guides/table-calculations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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}`.

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


### 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.
Expand Down Expand Up @@ -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)
</Frame>

## 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).
4 changes: 4 additions & 0 deletions guides/table-calculations/sql-templates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ mode: wide
sidebarTitle: Overview
---

<Tip>
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.
</Tip>

<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>

98 changes: 98 additions & 0 deletions references/table-calculation-functions/pivot-functions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: "Pivot functions"
description: "Built-in functions for accessing values across pivot columns in your table calculations."
---

<Info>
**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.
</Info>

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.

<Note>
Pivot functions are only available when your query includes a pivoted dimension.
</Note>

## 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})
```

<Accordion title="Compiled SQL">
```sql
ARRAY_AGG(${orders.total_revenue}) OVER (
PARTITION BY "row_index"
ORDER BY "column_index"
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)
```
</Accordion>

---

## 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)
```

<Accordion title="Compiled SQL">
```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.
</Accordion>
214 changes: 214 additions & 0 deletions references/table-calculation-functions/row-functions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
---
title: "Row functions"
description: "Built-in functions for accessing values from other rows in your table calculations."
---

<Info>
**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.
</Info>

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.

<Note>
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.
</Note>

## row

Returns the 1-based row number of the current row.

```
row()
```

**Parameters:** None

**Example**

Add a row number column to your results:

```
row()
```

<Accordion title="Compiled SQL">
```sql
ROW_NUMBER() OVER (ORDER BY ...)
```

The `ORDER BY` clause uses the sort order configured in your query.
</Accordion>

---

## 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)
```

<Accordion title="Compiled SQL">
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.
</Accordion>

---

## 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)
```

<Accordion title="Compiled SQL">
```sql
NTH_VALUE(${orders.total_revenue}, 1) OVER (
ORDER BY ...
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)
```
</Accordion>

---

## 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})
```

<Accordion title="Compiled SQL">
```sql
MAX(
CASE WHEN ${orders.status} = 'completed'
THEN ${orders.total_revenue}
ELSE NULL
END
) OVER ()
```
</Accordion>

---

## 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)
```

<Accordion title="Compiled SQL">
```sql
ARRAY[
LAG(${orders.total_revenue}, 2) OVER (ORDER BY ...),
LAG(${orders.total_revenue}, 1) OVER (ORDER BY ...),
${orders.total_revenue}
]
```
</Accordion>

---

## 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})
```

<Accordion title="Compiled SQL">
```sql
ARRAY[
${orders.total_revenue},
${orders.total_cost},
${orders.total_profit}
]
```
</Accordion>