Skip to content
Open
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
15 changes: 10 additions & 5 deletions documentation/cookbook/sql/time-series/fill-from-one-column.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,23 @@ WHERE symbol = 'EURUSD' AND timestamp IN '$today'
SAMPLE BY 100T FILL(PREV, PREV);
```

But when there is an interpolation, instead of getting the PREV value for `bid_price` and previous for `ask_price`, you want both prices to show the PREV known value for the `ask_price`. Imagine this SQL was valid:
But when there is an interpolation, instead of getting the PREV value for `bid_price` and previous for `ask_price`, you want both prices to show the PREV known value for the `ask_price`.

```sql
## Solution

QuestDB supports referencing another aggregate column by alias inside `PREV()`:

```questdb-sql demo title="Fill bid_price with previous value of ask_price"
SELECT timestamp, symbol, avg(bid_price) as bid_price, avg(ask_price) as ask_price
FROM core_price
WHERE symbol = 'EURUSD' AND timestamp IN '$today'
SAMPLE BY 100T FILL(PREV(ask_price), PREV);
```

## Solution

The only way to do this is in multiple steps within a single query: first get the sampled data interpolating with null values, then use a window function to get the last non-null value for the reference column, and finally coalesce the missing columns with this filler value.
The reference must match the target column's type, cannot be broadcast across
aggregates, and is rejected when either side is a `SYMBOL`. For more flexible
cases — for example, marking which rows were filled, or chaining custom
expressions — the equivalent rewrite below uses window functions:

```questdb-sql demo title="Fill bid and ask prices with value from ask price"
WITH sampled AS (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ and ending timestamp, not only between the first and last existing row in the fi

## Problem

QuestDB has a built-in [`SAMPLE BY .. FROM/TO`](/docs/query/sql/sample-by/#from-to) syntax available for non-keyed queries (queries that include only aggregated columns beyond the timestamp), and for the `NULL` FILL strategy.

If you use `FROM/TO` in a keyed query (for example, an OHLC with timestamp, symbol, and aggregations) you will get the
following error: _FROM-TO intervals are not supported for keyed SAMPLE BY queries_.
QuestDB's [`SAMPLE BY .. FROM/TO`](/docs/query/sql/sample-by/#from-to) supports
keyed queries when `FROM`/`TO` are constants. When the bounds are bind
variables, function calls, or arithmetic expressions (for example,
`dateadd('m', -2, now())`), the query is rejected with: _FROM-TO intervals are
not supported for keyed SAMPLE BY queries_. The recipe below works around this
limitation.


## Solution
Expand Down
32 changes: 19 additions & 13 deletions documentation/query/sql/sample-by.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,24 @@ SAMPLE BY 1h;

`FILL` specifies how to handle time intervals with no data. By default, missing intervals are skipped. Use `FILL` to interpolate or substitute values.

| fillOption | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------------------- |
| `NONE` | No fill applied. If there is no data, the time sample will be skipped in the results. A table could be missing intervals. |
| `NULL` | Fills with `NULL` values. |
| `PREV` | Fills using the previous value. |
| `LINEAR` | Fills by linear interpolation of the 2 surrounding points. |
| `x` | Fills with a constant value - where `x` is the desired value, for example `FILL(100.05)`. |
| fillOption | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------- |
| `NONE` | No fill applied. If there is no data, the time sample will be skipped in the results. A table could be missing intervals. |
| `NULL` | Fills with `NULL` values. |
| `PREV` | Fills using the previous value of the same aggregate column. |
| `PREV(col)` | Fills using the previous value of another aggregate column referenced by alias. |
| `LINEAR` | Fills by linear interpolation of the 2 surrounding points. |
| `x` | Fills with a constant value - where `x` is the desired value, for example `FILL(100.05)`. |

The following restrictions apply:

- Keywords denoting fill strategies may not be combined. Only one option from
`NONE`, `NULL`, `PREV`, `LINEAR` and constants may be used.
- `FILL(NONE)` cannot be combined with other fill values; the other strategies
may be mixed in a per-aggregate fill list.
- `LINEAR` strategy is not supported for keyed queries, i.e. queries that
contain non-aggregated columns other than the timestamp in the SELECT clause.
- `PREV(col)` references another aggregate column by alias and must match its
type. It cannot be broadcast across multiple aggregates and is rejected when
source or target is `SYMBOL`.
- The `FILL` keyword must precede alignment described in the
[sample calculation section](#sample-calculation), i.e.:

Expand Down Expand Up @@ -226,7 +230,7 @@ ALIGN TO CALENDAR TIME ZONE 'Europe/Berlin';
Here, `FROM '2026-01-01T00:00:00'` means midnight January 1st in Berlin local time
(= `2025-12-31T23:00:00Z` UTC).

`FROM-TO` can only be used on non-keyed SAMPLE BY queries (queries with no grouping columns other than the timestamp).
`FROM-TO` works with both non-keyed and keyed `SAMPLE BY` queries. Keyed queries emit one row per (bucket, key) combination across the full interval. Keyed `FROM-TO` requires `FROM`/`TO` to be constants; bind variables, function calls, or arithmetic expressions are rejected with _FROM-TO intervals are not supported for keyed SAMPLE BY queries_.

### `WHERE` clause optimisation

Expand All @@ -247,10 +251,12 @@ SAMPLE BY 1d FROM '2009-01-01' TO '2009-01-10' FILL(NULL);

### Limitations

- Not compatible with `FILL(PREV)` or `FILL(LINEAR)`.
- Not compatible with `FILL(LINEAR)`.
- Only works with `ALIGN TO CALENDAR` (default alignment).
- Does not consider any specified `OFFSET`.
- Only for non-keyed `SAMPLE BY` (designated timestamp and aggregate columns only). See [Fill keyed queries with arbitrary intervals](/docs/cookbook/sql/time-series/fill-keyed-arbitrary-interval/) for a workaround.
- Keyed `FROM-TO` requires `FROM`/`TO` to be constants. Bind variables,
function calls, and arithmetic expressions are rejected for keyed queries.
See [Fill keyed queries with arbitrary intervals](/docs/cookbook/sql/time-series/fill-keyed-arbitrary-interval/)
for a workaround.

## Sample calculation

Expand Down
Loading