# Time series functions

> 29 Time series functions in NYXDB: names, aliases, signatures and behaviour.

{/* AUTO-GENERATED from the function catalog. DO NOT EDIT — overwritten on every build. */}

29 functions. Names resolve case-insensitively; an alias binds the same function as its canonical name. Each entry gives the signatures, the behaviour and an example.

| Function | Summary |
| --- | --- |
| [`series_changes_to_grid`](#series_changes_to_grid) | Counts adjacent reading changes inside each regular-grid lookback interval. |
| [`series_copy_tag`](#series_copy_tag) | Copies one existing metadata-map entry to another key while retaining the source. |
| [`series_copy_tags`](#series_copy_tags) | Applies several metadata-key copies against one original map snapshot. |
| [`series_delta_rate`](#series_delta_rate) | Returns the signed per-second change since the previous accepted stream sample. |
| [`series_delta_sum`](#series_delta_sum) | Accumulates only upward changes between adjacent ordered measurements. |
| [`series_delta_sum_timestamp`](#series_delta_sum_timestamp) | Totals positive measurement increments ordered by their associated timestamps. |
| [`series_delta_to_grid`](#series_delta_to_grid) | Measures first-to-last gauge movement within each grid point’s lookback. |
| [`series_deriv_to_grid`](#series_deriv_to_grid) | Estimates a reading’s per-second linear-regression slope at regularly spaced instants. |
| [`series_exponential_moving_average`](#series_exponential_moving_average) | Smooths ordered observations with decay governed by elapsed time and a half-life. |
| [`series_extract_tag`](#series_extract_tag) | Looks up a metadata label by key and returns NULL when it is absent. |
| [`series_group_array`](#series_group_array) | Collects timestamped readings into a chronologically ordered array of pairs. |
| [`series_group_array_moving_avg`](#series_group_array_moving_avg) | Returns successive trailing-window means as a materialized observation history. |
| [`series_group_array_moving_sum`](#series_group_array_moving_sum) | Produces an ordered array of trailing-window totals for grouped readings. |
| [`series_instant_delta_to_grid`](#series_instant_delta_to_grid) | Subtracts the latest two fresh observations at each resampling instant. |
| [`series_instant_rate_to_grid`](#series_instant_rate_to_grid) | Calculates a counter’s recent per-second speed from its newest sample pair. |
| [`series_join_tags`](#series_join_tags) | Serializes a metadata map as deterministically sorted JSON object text. |
| [`series_last_to_grid`](#series_last_to_grid) | Carries the most recent fresh measurement onto each regular output timestamp. |
| [`series_last_two_samples`](#series_last_two_samples) | Retains the newest two timestamped observations with stable tie resolution. |
| [`series_predict_linear_to_grid`](#series_predict_linear_to_grid) | Forecasts future values from local timestamp-versus-reading regression. |
| [`series_rate_to_grid`](#series_rate_to_grid) | Averages reset-adjusted counter growth over each resampling lookback. |
| [`series_remove_all_tags_except`](#series_remove_all_tags_except) | Keeps only metadata entries named in an explicit allowlist. |
| [`series_remove_tag`](#series_remove_tag) | Returns a metadata map with one named entry removed. |
| [`series_remove_tags`](#series_remove_tags) | Deletes a supplied list of metadata keys in one immutable operation. |
| [`series_replace_tag`](#series_replace_tag) | Inserts or overwrites a metadata field with an explicitly supplied string value. |
| [`series_resample_to_grid_with_staleness`](#series_resample_to_grid_with_staleness) | Projects readings onto a regular timeline while expiring samples outside the freshness limit. |
| [`series_resets_to_grid`](#series_resets_to_grid) | Counts counter decreases observed within successive resampling windows. |
| [`series_running_difference`](#series_running_difference) | Emits consecutive numeric differences, starting a new non-NULL run at zero. |
| [`series_running_difference_starting_with_first_value`](#series_running_difference_starting_with_first_value) | Preserves the initial reading before emitting subsequent numeric increments. |
| [`series_sparkbar`](#series_sparkbar) | Draws a compact Unicode bar chart by aggregating measurements into horizontal bins. |

## series_changes_to_grid

Counts adjacent reading changes inside each regular-grid lookback interval.

```text
series_changes_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_changes_to_grid` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

At each grid point, counts unequal adjacent non-NULL samples in deterministic time order within the lookback. Insufficient fresh observations produce a NULL element; a nonpositive step, negative lookback or reversed endpoints raises INVALID_ARGUMENT. Sample history needs a finite window or state budget and raises RESOURCE_LIMIT if exhausted; final output waits for the watermark to pass the grid end.

**Example**

```sql
(
  SELECT
    series_changes_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [1]
```

## series_copy_tag

Copies one existing metadata-map entry to another key while retaining the source.

```text
series_copy_tag(tags:map(string,string), source_key:string, target_key:string) -> map(string,string)
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/ternary` |
| Returns | `map(string,string)` |
| Aliases | `time_series_copy_tag` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

Reads the source key from the input map and overwrites the target with that value when present. A missing source leaves the map unchanged; any NULL argument yields NULL. The map is immutable and must contain string keys and values, or binding raises TYPE_MISMATCH.

**Example**

```sql
series_copy_tag(map_from_arrays(['site'], ['north']), 'site', 'zone')
-- → {'site': 'north', 'zone': 'north'}
```

## series_copy_tags

Applies several metadata-key copies against one original map snapshot.

```text
series_copy_tags(tags:map(string,string), renames:map(string,string)) -> map(string,string)
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/binary` |
| Returns | `map(string,string)` |
| Aliases | `time_series_copy_tags` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

The rename map associates each source key with a destination, and all reads use the original metadata snapshot. Absent sources do nothing, duplicate destination names raise INVALID_ARGUMENT and NULL arguments produce NULL. Existing targets are overwritten without deleting their source entries or mutating the input map.

**Example**

```sql
series_copy_tags(
  map_from_arrays(['site'], ['north']),
  map_from_arrays(['site'], ['zone'])
)
-- → {'site': 'north', 'zone': 'north'}
```

## series_delta_rate

Returns the signed per-second change since the previous accepted stream sample.

```text
series_delta_rate(value:number, timestamp:datetime64(p,tz)) -> float64
```

| | |
| --- | --- |
| Kind | stream |
| Signature class | `stream/binary` |
| Returns | `float64` |
| Aliases | `delta_rate` |
| Streaming | Stateful — keeps per-group state. State: previous timestamp/value pair per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | first sample or NULL pair yields NULL; nonpositive elapsed time yields NULL |

Keeps the previous ordered timestamp/value pair per key and divides the value difference by elapsed seconds. The first sample, a NULL pair or a nonpositive elapsed interval returns NULL; duplicate or reversed times do not advance the retained timestamp. Only ordered append-only streaming is admitted, and incompatible ordering or retraction plans raise INVALID_ARGUMENT.

**Example**

```sql
series_delta_rate(10, TIMESTAMP '2026-01-01 00:00:00')
-- → NULL
```

## series_delta_sum

Accumulates only upward changes between adjacent ordered measurements.

```text
series_delta_sum(value:number) -> float64
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/unary` |
| Returns | `float64` |
| Aliases | `delta_sum` |
| Streaming | Stateful — keeps per-group state. State: previous value/time and accumulated positive differences per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Skips NULL values and adds positive differences between consecutive retained readings, treating a decrease as zero contribution. A single retained reading contributes zero, and deterministic source order is required. Streaming accepts ordered append-only input; retractions or unordered recomputation require a closed window, otherwise admission raises INVALID_ARGUMENT.

**Example**

```sql
(
  SELECT series_delta_sum(reading ORDER BY seq)
  FROM (VALUES (1, 10), (2, 14), (3, 3), (4, 8)) AS readings(seq, reading)
)
-- → 9
```

## series_delta_sum_timestamp

Totals positive measurement increments ordered by their associated timestamps.

```text
series_delta_sum_timestamp(value:number, timestamp:datetime64(p,tz)) -> float64
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/binary` |
| Returns | `float64` |
| Aliases | `delta_sum_timestamp` |
| Streaming | Stateful — keeps per-group state. State: previous value/time and accumulated positive differences per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Uses timestamps and stable source sequence to establish adjacent observations, adding increases while ignoring reset decreases. Rows with NULL measurement or timestamp are skipped, and the first retained observation contributes zero. Ordered append-only streaming retains predecessor state; incompatible retractions or unordered merges raise INVALID_ARGUMENT unless a closed window permits recomputation.

**Example**

```sql
(
  SELECT series_delta_sum_timestamp(reading, ts ORDER BY seq)
  FROM (
    VALUES (1, 10, TIMESTAMP '2026-01-01 00:00:00'),
    (2, 14, TIMESTAMP '2026-01-01 00:00:10')
  ) AS readings(seq, reading, ts)
)
-- → 4
```

## series_delta_to_grid

Measures first-to-last gauge movement within each grid point’s lookback.

```text
series_delta_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_delta_to_grid` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Computes the signed difference between the oldest and newest qualifying readings at each output instant. NULL samples are excluded, and fewer than two fresh observations produce a NULL element. Invalid grid parameters raise INVALID_ARGUMENT; exact sample retention requires finite windows or a state budget, and watermark finalization plus RESOURCE_LIMIT govern continuous evaluation.

**Example**

```sql
(
  SELECT
    series_delta_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [10]
```

## series_deriv_to_grid

Estimates a reading’s per-second linear-regression slope at regularly spaced instants.

```text
series_deriv_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_deriv_to_grid` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Fits value against timestamp in each lookback interval and returns the regression slope in seconds-based units. NULL pairs are skipped, and insufficient distinct sample times give a NULL array element. INVALID_ARGUMENT rejects malformed grid parameters; regression history remains subject to RESOURCE_LIMIT, and continuous output finalizes only beyond the grid-end watermark.

**Example**

```sql
(
  SELECT
    series_deriv_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [1]
```

## series_exponential_moving_average

Smooths ordered observations with decay governed by elapsed time and a half-life.

```text
series_exponential_moving_average(half_life:float64; value:number, timeunit:float64) -> float64
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/ternary+parametric` |
| Returns | `float64` |
| Aliases | `exponential_moving_average` |
| Streaming | Stateful — keeps per-group state. State: weighted numerator/denominator and latest time per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Weights prior observations by exponential decay as the time-unit argument advances, using a positive constant half-life. NULL observation pairs are skipped and a lone contributing value defines its own average. Invalid half-life raises INVALID_ARGUMENT; streaming admits ordered append-only updates, with out-of-order changes or retractions requiring closed-window recomputation.

**Example**

```sql
(
  SELECT series_exponential_moving_average(10)(reading, elapsed)
  FROM (VALUES (12, 0)) AS readings(reading, elapsed)
)
-- → 12
```

## series_extract_tag

Looks up a metadata label by key and returns NULL when it is absent.

```text
series_extract_tag(tags:map(string,string), key:string) -> string NULL
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/binary` |
| Returns | `string NULL` |
| Aliases | `time_series_extract_tag` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL argument or absent key yields NULL |

Returns the string value stored under the exact key in a typed metadata map. SQL NULL in either argument or a missing key produces NULL rather than an empty string. There is no external dictionary lookup; maps with incompatible key or value types raise TYPE_MISMATCH.

**Example**

```sql
series_extract_tag(map_from_arrays(['site'], ['north']), 'site')
-- → 'north'
```

## series_group_array

Collects timestamped readings into a chronologically ordered array of pairs.

```text
series_group_array(timestamp:datetime64(p,tz), value:number) -> array(tuple(datetime64(p,tz),float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/binary` |
| Returns | `array(tuple(datetime64(p,tz),float64))` |
| Aliases | `time_series_group_array` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Sorts retained timestamp/value pairs by timestamp with stable source sequence for equal times, preserving duplicate timestamps. NULL pairs are skipped and an empty group yields an empty array. Continuous groups need finite event-time windows or explicit cardinality admission; exceeding that state budget raises RESOURCE_LIMIT.

**Example**

```sql
(
  SELECT series_group_array(ts, reading)
  FROM (VALUES (TIMESTAMP '2026-01-01 00:00:00', 12)) AS readings(ts, reading)
)
-- → [(2026-01-01 00:00:00, 12)]
```

## series_group_array_moving_avg

Returns successive trailing-window means as a materialized observation history.

```text
series_group_array_moving_avg(window:uint32; value:number) -> array(float64)
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/binary+parametric` |
| Returns | `array(float64)` |
| Aliases | `group_array_moving_avg` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Divides each trailing window total by the configured positive window size, counting unfilled initial slots as zero contributions. NULL observations are skipped rather than occupying a slot, and empty input yields an empty array. Zero window size raises INVALID_ARGUMENT; continuous materialization requires a finite group or state budget, with RESOURCE_LIMIT on exhaustion.

**Example**

```sql
(
  SELECT series_group_array_moving_avg(2)(reading ORDER BY seq)
  FROM (VALUES (1, 2), (2, 4), (3, 6)) AS readings(seq, reading)
)
-- → [1, 3, 5]
```

## series_group_array_moving_sum

Produces an ordered array of trailing-window totals for grouped readings.

```text
series_group_array_moving_sum(window:uint32; value:number) -> array(float64)
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/binary+parametric` |
| Returns | `array(float64)` |
| Aliases | `group_array_moving_sum` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

For each retained observation, sums up to the configured number of preceding values including the current one. NULL values are skipped; an empty group produces an empty array, and a zero window raises INVALID_ARGUMENT. The working ring is bounded but the output grows, so continuous use needs a finite window or state budget and may raise RESOURCE_LIMIT.

**Example**

```sql
(
  SELECT series_group_array_moving_sum(2)(reading ORDER BY seq)
  FROM (VALUES (1, 1), (2, 2), (3, 3)) AS readings(seq, reading)
)
-- → [1, 3, 5]
```

## series_instant_delta_to_grid

Subtracts the latest two fresh observations at each resampling instant.

```text
series_instant_delta_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_instant_delta_to_grid` |
| Streaming | Stateful — keeps per-group state. State: grid_points times two latest sample pairs per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Uses only the two newest qualifying samples in the lookback and returns their signed value difference. A missing pair after NULL filtering produces a NULL element, with no counter-reset correction applied. Invalid timing bounds raise INVALID_ARGUMENT; streaming keeps the needed latest samples per grid point and releases finalized output after the watermark crosses the grid end.

**Example**

```sql
(
  SELECT
    series_instant_delta_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [10]
```

## series_instant_rate_to_grid

Calculates a counter’s recent per-second speed from its newest sample pair.

```text
series_instant_rate_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_instant_rate_to_grid` |
| Streaming | Stateful — keeps per-group state. State: grid_points times two latest sample pairs per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Divides the reset-adjusted increase between the latest two qualifying samples by their elapsed seconds. A decrease denotes a reset to zero, while NULL pairs, insufficient freshness or unusable elapsed time yield a NULL grid element. Invalid grid parameters raise INVALID_ARGUMENT; streaming retains bounded pair state per admitted point and finalizes after the grid-end watermark.

**Example**

```sql
(
  SELECT
    series_instant_rate_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [1]
```

## series_join_tags

Serializes a metadata map as deterministically sorted JSON object text.

```text
series_join_tags(tags:map(string,string)) -> string
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/unary` |
| Returns | `string` |
| Aliases | `time_series_join_tags` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

Orders keys canonically and writes JSON escaping for every string key and value. The resulting string distinguishes embedded separators unambiguously and uses a versioned encoding contract. NULL input yields NULL, incompatible map descriptors raise TYPE_MISMATCH and output exceeding its byte budget raises RESOURCE_LIMIT.

**Example**

```sql
series_join_tags(map_from_arrays(['site'], ['north']))
-- → '{"site":"north"}'
```

## series_last_to_grid

Carries the most recent fresh measurement onto each regular output timestamp.

```text
series_last_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_last_to_grid` |
| Streaming | Stateful — keeps per-group state. State: grid_points times two latest sample pairs per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Selects the latest non-NULL timestamp/value pair within each grid point’s lookback. A point without a qualifying sample receives NULL, so stale observations are not carried indefinitely. A nonpositive step or invalid time range raises INVALID_ARGUMENT; streaming retains latest-sample state per bounded grid and finalizes once the watermark passes its end.

**Example**

```sql
(
  SELECT
    series_last_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [20]
```

## series_last_two_samples

Retains the newest two timestamped observations with stable tie resolution.

```text
series_last_two_samples(timestamp:datetime64(p,tz), value:number) -> array(tuple(datetime64(p,tz),float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/binary` |
| Returns | `array(tuple(datetime64(p,tz),float64))` |
| Aliases | `time_series_last_two_samples` |
| Streaming | Stateful — keeps per-group state. State: last two timestamp/value pairs per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Returns zero, one or two non-NULL timestamp/value pairs selected by greatest timestamp and stable source order. NULL pairs do not become retained samples, and the returned entries preserve their chronological order. Append-only arrival can use bounded two-sample state, but retractable use needs a finite window and raises RESOURCE_LIMIT if its admitted history is exceeded.

**Example**

```sql
(
  SELECT series_last_two_samples(ts, reading)
  FROM (VALUES (TIMESTAMP '2026-01-01 00:00:00', 12)) AS readings(ts, reading)
)
-- → [(2026-01-01 00:00:00, 12)]
```

## series_predict_linear_to_grid

Forecasts future values from local timestamp-versus-reading regression.

```text
series_predict_linear_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64, forecast_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/7-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_predict_linear_to_grid` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Fits a line to the qualifying observations and evaluates it at the grid instant plus the constant forecast horizon. NULL pairs are skipped; inadequate fresh data or indistinguishable times produce NULL for that prediction. Nonfinite horizons or invalid grid settings raise INVALID_ARGUMENT, while RESOURCE_LIMIT bounds regression history and continuous results await the closing watermark.

**Example**

```sql
(
  SELECT
    series_predict_linear_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20,
      10
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [30]
```

## series_rate_to_grid

Averages reset-adjusted counter growth over each resampling lookback.

```text
series_rate_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_rate_to_grid` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Accumulates counter increases across the qualifying interval, treating decreases as resets to zero, and divides by elapsed seconds. NULL observations are skipped and insufficient fresh samples produce NULL rather than zero throughput. Invalid timing constants raise INVALID_ARGUMENT; exact history requires an admitted finite window or state cap, with RESOURCE_LIMIT and grid-end watermark finalization enforced.

**Example**

```sql
(
  SELECT
    series_rate_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [1]
```

## series_remove_all_tags_except

Keeps only metadata entries named in an explicit allowlist.

```text
series_remove_all_tags_except(tags:map(string,string), keys:array(string)) -> map(string,string)
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/binary` |
| Returns | `map(string,string)` |
| Aliases | `time_series_remove_all_tags_except` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

Filters the map by exact membership in the supplied key array and discards all other entries. Unknown allowlist names add nothing, and an empty allowlist produces an empty map. SQL NULL propagates; incompatible map or array types raise TYPE_MISMATCH, with retained keys still canonically sorted.

**Example**

```sql
series_remove_all_tags_except(
  map_from_arrays(['site', 'unit'], ['north', 'C']),
  ['unit']
)
-- → {'unit': 'C'}
```

## series_remove_tag

Returns a metadata map with one named entry removed.

```text
series_remove_tag(tags:map(string,string), key:string) -> map(string,string)
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/binary` |
| Returns | `map(string,string)` |
| Aliases | `time_series_remove_tag` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

Deletes the exact key from an immutable copy and leaves every other key/value association unchanged. A missing key is harmless and the output retains canonical key ordering. NULL arguments produce NULL; nonstring-keyed metadata raises TYPE_MISMATCH.

**Example**

```sql
series_remove_tag(map_from_arrays(['site', 'unit'], ['north', 'C']), 'site')
-- → {'unit': 'C'}
```

## series_remove_tags

Deletes a supplied list of metadata keys in one immutable operation.

```text
series_remove_tags(tags:map(string,string), keys:array(string)) -> map(string,string)
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/binary` |
| Returns | `map(string,string)` |
| Aliases | `time_series_remove_tags` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

Removes each listed key from the input string map while preserving values under unlisted keys. Repeated removal names and absent keys have no additional effect; NULL arguments return NULL. A key-list element outside the required string contract raises TYPE_MISMATCH, and the remaining map stays canonically ordered.

**Example**

```sql
series_remove_tags(
  map_from_arrays(['site', 'unit'], ['north', 'C']),
  ['site',
  'missing']
)
-- → {'unit': 'C'}
```

## series_replace_tag

Inserts or overwrites a metadata field with an explicitly supplied string value.

```text
series_replace_tag(tags:map(string,string), key:string, value:string) -> map(string,string)
```

| | |
| --- | --- |
| Kind | scalar |
| Signature class | `scalar/ternary` |
| Returns | `map(string,string)` |
| Aliases | `time_series_replace_tag` |
| Streaming | Continuous — evaluated per row with no retained state. |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | Any NULL argument gives NULL. |

Creates a new map containing the requested association whether or not the key previously existed. All other entries remain unchanged, and no external state or dictionary is modified. Any NULL argument yields NULL; TYPE_MISMATCH rejects incompatible metadata types and RESOURCE_LIMIT bounds the resulting map.

**Example**

```sql
series_replace_tag(map_from_arrays(['site'], ['north']), 'site', 'south')
-- → {'site': 'south'}
```

## series_resample_to_grid_with_staleness

Projects readings onto a regular timeline while expiring samples outside the freshness limit.

```text
series_resample_to_grid_with_staleness(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_resample_to_grid_with_staleness` |
| Streaming | Stateful — keeps per-group state. State: grid_points times two latest sample pairs per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Uses the most recent eligible observation at each grid position and clears its contribution after the lookback freshness interval. NULL source pairs are ignored, and an expired or absent observation becomes a NULL output element. Invalid grid constants raise INVALID_ARGUMENT; bounded per-point retention and watermark closure govern streaming, with RESOURCE_LIMIT rejecting excessive grid cardinality.

**Example**

```sql
(
  SELECT
    series_resample_to_grid_with_staleness(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [20]
```

## series_resets_to_grid

Counts counter decreases observed within successive resampling windows.

```text
series_resets_to_grid(grid_start:datetime64(p,tz), grid_end:datetime64(p,tz), step_seconds:float64, lookback_seconds:float64; timestamp:datetime64(p,tz), value:number) -> array(nullable(float64))
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/6-ary+parametric` |
| Returns | `array(float64 NULL)` |
| Aliases | `time_series_resets_to_grid` |
| Streaming | Stateful — keeps per-group state. State: unbounded |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Treats a decrease between adjacent retained readings as a reset event and counts these events for each grid point. NULL samples are skipped, and insufficient fresh data leaves a NULL element rather than asserting no resets. Invalid grid bounds or timing parameters raise INVALID_ARGUMENT; bounded streaming history finalizes after the watermark passes the last grid time and RESOURCE_LIMIT enforces admission.

**Example**

```sql
(
  SELECT
    series_resets_to_grid(
      TIMESTAMP '2026-01-01 00:00:10',
      TIMESTAMP '2026-01-01 00:00:10',
      10,
      20
    )(ts, reading)
  FROM (
    VALUES (TIMESTAMP '2026-01-01 00:00:00', 10),
    (TIMESTAMP '2026-01-01 00:00:10', 20)
  ) AS readings(ts, reading)
)
-- → [0]
```

## series_running_difference

Emits consecutive numeric differences, starting a new non-NULL run at zero.

```text
series_running_difference(value:int8|int16|int32|int64|uint8|uint16|uint32) -> int64
series_running_difference(value:uint64|int128) -> int128
series_running_difference(value:uint128|int256|uint256) -> int256
series_running_difference(value:float32|float64) -> float64
series_running_difference(value:decimal(P,S)) -> decimal(P,S)
```

| | |
| --- | --- |
| Kind | stream |
| Signature class | `stream/unary` |
| Returns | `signed width promotion; float64; decimal(P,S); checked overflow` |
| Aliases | `running_difference` |
| Streaming | Stateful — keeps per-group state. State: one previous value per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL yields NULL and clears previous value; first non-NULL yields zero |

Subtracts the preceding value in explicit per-key order using the declared widened result type. NULL emits NULL and clears the predecessor, so the next present value emits zero; checked decimal or wide-integer overflow raises NUMERIC_OVERFLOW. Ordered append-only streaming retains state across execution blocks, and incompatible retraction or ordering plans raise INVALID_ARGUMENT.

**Example**

```sql
series_running_difference(10)
-- → 0
```

## series_running_difference_starting_with_first_value

Preserves the initial reading before emitting subsequent numeric increments.

```text
series_running_difference_starting_with_first_value(value:int8|int16|int32|int64|uint8|uint16|uint32) -> int64
series_running_difference_starting_with_first_value(value:uint64|int128) -> int128
series_running_difference_starting_with_first_value(value:uint128|int256|uint256) -> int256
series_running_difference_starting_with_first_value(value:float32|float64) -> float64
series_running_difference_starting_with_first_value(value:decimal(P,S)) -> decimal(P,S)
```

| | |
| --- | --- |
| Kind | stream |
| Signature class | `stream/unary` |
| Returns | `signed width promotion; float64; decimal(P,S); checked overflow` |
| Aliases | `running_difference_starting_with_first_value` |
| Streaming | Stateful — keeps per-group state. State: one previous value per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL yields NULL and clears previous value; first non-NULL yields its input value |

Returns the first non-NULL value of each run, then emits differences from its predecessor using the contract’s promoted numeric type. NULL produces NULL and clears the run; unrepresentable checked differences raise NUMERIC_OVERFLOW. The predecessor survives execution-block boundaries, and continuous admission requires deterministic per-key append order or raises INVALID_ARGUMENT.

**Example**

```sql
series_running_difference_starting_with_first_value(10)
-- → 10
```

## series_sparkbar

Draws a compact Unicode bar chart by aggregating measurements into horizontal bins.

```text
series_sparkbar(width:uint16, minimum:float64, maximum:float64; x:number, y:number) -> string
```

| | |
| --- | --- |
| Kind | aggregate |
| Signature class | `aggregate/5-ary+parametric` |
| Returns | `string` |
| Aliases | `sparkbar` |
| Streaming | Stateful — keeps per-group state. State: width histogram accumulators per key |
| Determinism | Deterministic — the same arguments always give the same result. |
| NULL handling | NULL inputs are skipped. |

Places each x coordinate in a fixed-width interval and aggregates its y contribution before rendering block heights. NULL pairs and coordinates outside the supplied range are ignored; an empty group returns an empty string. Width outside one through 65535 or minimum not below maximum raises INVALID_ARGUMENT, and bounded bin state supports continuous aggregation.

**Example**

```sql
(
  SELECT series_sparkbar(3, 0, 3)(x, y)
  FROM (VALUES (1, 2)) AS readings(x, y)
  WHERE FALSE
)
-- → ''
```

---

Source: https://nyxdb.io/docs/functions/time-series/
