afv-library/skills/explaining-batch-data-transform/references/bdt-window-functions.md
Gaurav Bajpai 9c47f28221
feat(bdt): reference docs + sample BDTs @W-22196528@
Adds the curated reference library the skill loads on demand, plus
four synthetic sample BDTs used by docs, tests, and LLM-mode demos.

references/ (4 curated Markdown files):
- bdt-reference.md        — top-level BDT JSON anatomy: envelope,
                            nodes, edges, UI layer, definitions,
                            businessType semantics. Cites the core-262
                            upstream JSON schema and Connect API spec.
- bdt-node-catalog.md     — every node type (DMO Source, DMO Sink,
                            Filter, Join, Union, Aggregate, Window,
                            Formula, Split, Append, etc.) with its
                            required/optional fields and typical
                            usage. Audited against core-262 enums.
- bdt-function-catalog.md — the expression-language function surface
                            (string, numeric, date, conditional,
                            aggregate). Grouped by category with
                            signature + one-line semantics.
- bdt-window-functions.md — windowing operators (ROW_NUMBER, RANK,
                            LEAD/LAG, running aggregates) with PARTITION
                            BY / ORDER BY grammar and gotchas.

assets/sample_bdts/ (4 synthetic, dependency-free BDTs):
- minimal_dmo_to_dmo.json   — smallest valid BDT (1 source, 1 sink).
- joins_and_filters.json    — join + filter composition.
- window_and_aggregate.json — window function + aggregate in one graph.
- append_and_split.json     — append-then-split branching topology.

Grounding rules enforced in this commit:
- Every claim in references/ cites an upstream source (core-262 JSON
  schema, Connect API reference, or the Data Cloud BDT editor spec).
  No speculative content.
- No raw DITA or internal-only documentation is shipped; references
  are synthesized from public-facing material.
- BusinessTypeEnum values use the canonical camelCase casing from
  core-262 (case-cleanup fix included here).
- Sample BDTs are original synthetic fixtures, not redacted customer
  data. Each is small enough to read end-to-end.

@W-22196528@
2026-04-23 23:29:05 +05:30

3.8 KiB

Window Functions — for computeRelative nodes

Last synced: 2026-04-23 from the SFSQL window-functions reference and the BDT canonical schema. Consult this file whenever narrating a computeRelative node or explaining a window-function expression.

When this applies

computeRelative nodes evaluate a window function over rows. The parameters:

{
  "partitionBy": ["ssot__AccountId__c"],              // → SQL `PARTITION BY`
  "orderBy": [                                         // → SQL `ORDER BY`
    {"fieldName": "ssot__CreatedDate__c", "direction": "ASC"}
  ],
  "expressionType": "SQL",                             // or "DCSQL"
  "fields": [
    {
      "name": "OrderRank__c",
      "formulaExpression": "row_number()",             // the window function call
      "type": "NUMBER", "businessType": "Number",
      "precision": 18, "scale": 0
    }
  ]
}

The formulaExpression names the window function; partitioning and ordering come from the top-level partitionBy and orderBy. A computeRelative node may include at most one compute-relative function per expression (per upstream BDT docs).

Available window functions

Function Returns What it does
row_number() NUMBER 1, 2, 3… for each row in its partition, in the given order. Non-deterministic when sort keys tie.
rank() NUMBER Like row_number but peers share a rank; next rank after N peers is N+1 (gaps).
dense_rank() NUMBER Like rank but no gaps — consecutive integers even with ties.
percent_rank() NUMBER (rank - 1) / (partition_rows - 1) — relative rank within partition, 0 to 1.
cume_dist() NUMBER Cumulative distribution: fraction of partition rows at or before current.
ntile(n) NUMBER Bucket number 1..n, dividing partition rows as evenly as possible.
lag(value) / lag(value, offset) / lag(value, offset, default) same as value Value at offset rows before current (default offset=1; default if no such row is NULL unless a default is supplied).
lead(value) / lead(value, offset) / lead(value, offset, default) same as value Symmetric with lag but looks forward.
first_value(value) same as value Value at the first row of the current window frame.
last_value(value) same as value Value at the last row of the frame. Default frame ends at "current + peers", which is often not what users want.
nth_value(value, n) same as value Value at the nth row of the frame (counting from 1). NULL if no such row.
Any aggregate with OVER(...) depends Runs the aggregate over the window (running sum, etc.).

How this maps to BDT JSON

  • partitionBy is the SQL PARTITION BY — the columns that group rows into windows.
  • orderBy is the SQL ORDER BY — the ordering within each partition.
  • Peers are rows with identical sort keys.
  • Default frame (when not otherwise specified): rows from the first row of the partition through the current row's last peer. For last_value and nth_value this is often not the user's intent — narrate accordingly.

Common narration patterns

  • row_number() partitioned by X → "numbers each row within the same X, in the order given by orderBy."
  • rank() partitioned by X order by Y → "ranks rows within each X group by Y; ties share a rank and the next rank has gaps."
  • case when row_number()=1 then VAL else 0 end → "keeps VAL only on the first ranked row per partition; everything else is 0. This is the canonical 'first-occurrence extract' idiom."

Sources

  • SFSQL window-functions reference (internal Data Cloud / SDB SFSQL docs).
  • BDT canonical schema: ComputeRelativeParametersInputRepresentation, ComputeRelativeSortParametersInputRepresentation.