Grouping, spanners and pivots

Pivot tables

Use a pivot when you need to cross-tabulate one measure across two categorical fields instead of listing every row.

What you can do

  • pivot lives inside TableSpec alongside columns; when both are present, pivot wins, since the schema has no oneOf between them.
  • rows and columns are each a non-empty array of field names that become the pivot’s row and column axes.
  • values holds 1-20 PivotValue entries, each a field plus an optional agg (sum, avg, min, max, count) that becomes one generated data column per column-axis combination.
  • weightField on a PivotValue computes a weighted aggregate instead of a plain one; label, format, align, colorScale, cell, and conditionalFormat all apply per value the same as on a regular column.
  • totals turns on row, column, and/or grand summary rows/columns; maxColumns (1-200, default 50) caps how many generated columns the pivot can produce.

pivot only appears inside a table panel’s spec; there is no pivot equivalent on any chart:* panel.

Spec

View spec
{
  "id": "regional-pivot",
  "type": "table",
  "title": "Revenue by category and region",
  "data": {
    "rows": [
      {
        "category": "Hardware",
        "region": "West",
        "revenue": 420000,
        "units": 1200
      },
      {
        "category": "Hardware",
        "region": "East",
        "revenue": 310000,
        "units": 900
      },
      {
        "category": "Software",
        "region": "West",
        "revenue": 560000,
        "units": 2100
      },
      {
        "category": "Software",
        "region": "East",
        "revenue": 480000,
        "units": 1800
      }
    ]
  },
  "spec": {
    "pivot": {
      "rows": [
        "category"
      ],
      "columns": [
        "region"
      ],
      "values": [
        {
          "field": "revenue",
          "agg": "sum",
          "weightField": "units",
          "format": {
            "type": "currency",
            "currency": "USD",
            "compact": true
          }
        }
      ],
      "totals": {
        "row": true,
        "column": true,
        "grand": true
      },
      "maxColumns": 50
    }
  }
}

weightField on the revenue value computes a units-weighted sum instead of a plain sum, and totals adds row, column, and grand summary cells.

Try it live

Open the rich-tables dashboard in the live demo

Open the rich-tables template, page by-quarter, panel bq-revenue for a category-by-quarter pivot with a colorScale on the values, and panel bq-discount for a weighted-average pivot with row, column, and grand totals.

Build it in dvt

Every table capability on this site is a few lines of the same declarative JSON spec. Read the full spec format, or connect an AI agent to your warehouse and build one live in the quickstart.

Follow the build

dvt is in founding research. Leave your email and we'll reach out when there's something to see — no newsletters, no noise.

No spam. We use this to reach out directly, nothing else.