Skip to content

feat(metrics): add MEDIAN/STDDEV_SAMP/VAR_SAMP as system-wide aggregates - #42895

Open
rusackas wants to merge 4 commits into
masterfrom
sip/median-stddev-variance-aggregates
Open

feat(metrics): add MEDIAN/STDDEV_SAMP/VAR_SAMP as system-wide aggregates#42895
rusackas wants to merge 4 commits into
masterfrom
sip/median-stddev-variance-aggregates

Conversation

@rusackas

@rusackas rusackas commented Aug 7, 2026

Copy link
Copy Markdown
Member

SUMMARY

This now has a working implementation alongside docs/sip/median-stddev-variance-aggregates.md, so reviewers (and PMC members this gets shared with) have a concrete design to react to rather than just a description of one. Still opened as a draft: the point is to pressure-test the framing and scope before this goes up for a formal SIP vote, not to pre-empt that discussion.

Prompted by a report that Pivot Table lost several aggregation options somewhere along the way. Short version: most of what looked missing (Count Unique Values, Count/Average/Max/Min, "as fraction of" display) already has an equivalent today, see the doc for specifics. MEDIAN, STDDEV_SAMP (Sample Standard Deviation), and VAR_SAMP (Sample Variance) are genuinely gone, system-wide, not just Pivot Table, since #41184 (SIP-216) deliberately removed the old pivot-only "Aggregation function" control as the mechanism behind our long-standing wrong-totals bug. Not purely hypothetical either: the MCP chart-creation service already advertised STDDEV/VAR as valid aggregates that never matched any real Superset aggregate name, so MCP-built charts using them always errored at query time — fixed here too, normalized to the real names.

What's implemented:

  • MEDIAN/STDDEV_SAMP/VAR_SAMP added to the system-wide Aggregate type and the metric-picker dropdown (every chart type, not a Pivot-Table-specific control).
  • A new BaseEngineSpec.get_extended_aggregation_func extensibility point (mirrors supports_grouping_sets/_time_grain_expressions, both from feat(table/pivot-table): correct non-additive totals/subtotals via DB rollup [SIP-216] #41184) — engines opt in only once verified, unsupported engines get a clear "not supported on this database" error instead of unverified SQL.
  • Enabled for Postgres, MySQL (STDDEV_SAMP/VAR_SAMP only, no native MEDIAN), DuckDB, and Redshift (inherits Postgres, not separately verified) — each verified against a live instance, not just documentation (see commit message / SIP doc for the exact per-engine findings, including a real MySQL landmine: its VARIANCE() is population variance, not sample).
  • Zero Pivot-Table-specific code: these aggregates fall outside ADDITIVE_AGGREGATES automatically, so totals/subtotals already route through the correct DB-rollup path SIP-216 introduced — same mechanism that already makes AVG/COUNT_DISTINCT correct today.
  • MCP's STDDEV/VAR shorthand normalized to STDDEV_SAMP/VAR_SAMP.

Explicitly out of scope, per the doc: First/Last (no unambiguous SQL meaning as a plain aggregate without an explicit ordering) and List Unique Values (dialect + unbounded-payload questions) — flagged as candidate follow-up SIPs.

TESTING INSTRUCTIONS

Backend: pytest tests/unit_tests/db_engine_specs/test_base.py tests/unit_tests/db_engine_specs/test_postgres.py tests/unit_tests/db_engine_specs/test_mysql.py tests/unit_tests/db_engine_specs/test_duckdb.py tests/unit_tests/db_engine_specs/test_redshift.py tests/unit_tests/models/helpers_test.py tests/unit_tests/mcp_service/

Frontend: npx jest plugins/plugin-chart-pivot-table/test/plugin/utilities.test.ts (confirms the new aggregates are automatically treated as non-additive, with no pivot-table code changes).

Manually: on a Postgres-backed dataset, create a chart with a MEDIAN/STDDEV_SAMP/VAR_SAMP metric; on a SQLite-backed one, confirm the same aggregate now returns a clear "not supported on this database" error rather than a generic one.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration
  • Introduces new feature or API
  • Removes existing feature or API

@github-actions github-actions Bot added preset-io doc Namespace | Anything related to documentation labels Aug 7, 2026
@netlify

netlify Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit f02ef22
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a76bca52f60db00087e44b6
😎 Deploy Preview https://deploy-preview-42895--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@pull-request-size pull-request-size Bot added size/XL and removed size/L labels Aug 7, 2026
@rusackas rusackas changed the title docs(sip): propose system-wide MEDIAN/STDDEV_SAMP/VAR_SAMP metric aggregates feat(metrics): add MEDIAN/STDDEV_SAMP/VAR_SAMP as system-wide aggregates Aug 7, 2026
@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.28571% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.41%. Comparing base (d8b97e3) to head (cefee1b).
⚠️ Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
superset/models/helpers.py 0.00% 7 Missing ⚠️
superset/connectors/sqla/models.py 14.28% 5 Missing and 1 partial ⚠️
superset/mcp_service/chart/chart_utils.py 0.00% 2 Missing ⚠️
superset/db_engine_specs/base.py 80.00% 1 Missing ⚠️
.../mcp_service/chart/validation/dataset_validator.py 0.00% 1 Missing ⚠️
...rvice/chart/validation/runtime/format_validator.py 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master   #42895   +/-   ##
=======================================
  Coverage   66.40%   66.41%           
=======================================
  Files        2857     2857           
  Lines      161303   161357   +54     
  Branches    37133    37137    +4     
=======================================
+ Hits       107120   107160   +40     
- Misses      52158    52171   +13     
- Partials     2025     2026    +1     
Flag Coverage Δ
hive 38.27% <72.85%> (+0.02%) ⬆️
javascript 73.23% <ø> (-0.01%) ⬇️
mysql 57.80% <74.28%> (+0.01%) ⬆️
postgres 57.84% <74.28%> (+0.01%) ⬆️
presto 40.23% <72.85%> (+0.02%) ⬆️
python 59.24% <74.28%> (+0.01%) ⬆️
sqlite 57.47% <74.28%> (+0.01%) ⬆️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rusackas
rusackas marked this pull request as ready for review August 8, 2026 04:21
@rusackas
rusackas requested a review from sadpandajoe August 8, 2026 04:21
@dosubot dosubot Bot added change:backend Requires changing the backend change:frontend Requires changing the frontend data:connect:duckdb Related to a specific database data:connect:mysql Related to MySQL data:connect:postgres Related to Postgres data:connect:redshift Related to Redshift explore:metrics Related to metrics of Explore viz:charts:pivot Related to the Pivot Table charts labels Aug 8, 2026
claude added 3 commits August 7, 2026 22:10
…regates [DRAFT/SIP]

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tes [DRAFT/SIP]

Implements the proposal in docs/sip/median-stddev-variance-aggregates.md:
MEDIAN, STDDEV_SAMP, and VAR_SAMP are now selectable anywhere a metric
aggregate is chosen, not just Pivot Table. Support is opt-in per engine
via a new BaseEngineSpec.get_extended_aggregation_func hook (mirroring
supports_grouping_sets/_time_grain_expressions), verified against live
Postgres/MySQL/DuckDB instances before being enabled; unsupported engines
raise a clear error instead of emitting unverified SQL. No pivot-table-
specific code needed: these aggregates fall outside ADDITIVE_AGGREGATES
automatically, so totals/subtotals already route through the correct
DB-rollup path SIP-216 (#41184) introduced.

Also fixes a live bug this surfaced: the MCP chart-creation service
advertised STDDEV/VAR as valid aggregates that never matched any real
Superset aggregate name, so MCP-built charts using them always errored
at query time. Now normalized to STDDEV_SAMP/VAR_SAMP.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… decided

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@rusackas
rusackas force-pushed the sip/median-stddev-variance-aggregates branch from 8305f5e to f02ef22 Compare August 8, 2026 05:20
Comment thread superset/db_engine_specs/base.py
Comment thread superset/models/helpers.py
Comment thread superset/mcp_service/chart/validation/runtime/format_validator.py Outdated
Comment thread superset/utils/core.py
@bito-code-review

bito-code-review Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #ecf60a

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/mcp_service/chart/prompts/create_chart_guided.py - 1
    • Incomplete aggregate list · Line 139-142
      The documentation update correctly replaces ambiguous `STDDEV/VAR` with `STDDEV_SAMP/VAR_SAMP`. However, `PERCENTILE` is a valid aggregate in `schemas.py:796` and `chart_utils.py:616` but is missing from this list. Users guided by this prompt won't know PERCENTILE is available.
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset/mcp_service/chart/validation/runtime/format_validator.py - 1
Review Details
  • Files reviewed - 22 · Commit Range: c7fd626..f02ef22
    • superset-frontend/packages/superset-ui-core/src/query/types/Metric.ts
    • superset-frontend/plugins/plugin-chart-pivot-table/test/plugin/utilities.test.ts
    • superset-frontend/src/explore/constants.ts
    • superset/connectors/sqla/models.py
    • superset/db_engine_specs/base.py
    • superset/db_engine_specs/duckdb.py
    • superset/db_engine_specs/mysql.py
    • superset/db_engine_specs/postgres.py
    • superset/mcp_service/chart/chart_utils.py
    • superset/mcp_service/chart/prompts/create_chart_guided.py
    • superset/mcp_service/chart/schemas.py
    • superset/mcp_service/chart/validation/dataset_validator.py
    • superset/mcp_service/chart/validation/runtime/format_validator.py
    • superset/models/helpers.py
    • superset/utils/core.py
    • tests/unit_tests/db_engine_specs/test_base.py
    • tests/unit_tests/db_engine_specs/test_duckdb.py
    • tests/unit_tests/db_engine_specs/test_mysql.py
    • tests/unit_tests/db_engine_specs/test_postgres.py
    • tests/unit_tests/db_engine_specs/test_redshift.py
    • tests/unit_tests/mcp_service/chart/test_chart_utils.py
    • tests/unit_tests/models/helpers_test.py
  • Files skipped - 2
    • UPDATING.md - Reason: Filter setting
    • docs/sip/median-stddev-variance-aggregates.md - Reason: Filter setting
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

MEDIAN/STDDEV_SAMP/VAR_SAMP were only verified against live Postgres,
MySQL, DuckDB, and Redshift instances, but `_extended_aggregations`
lived on `PostgresBaseEngineSpec`/`PostgresEngineSpec`/`MySQLEngineSpec`,
so every other subclass (Vertica, Netezza, HANA, Snowflake, CockroachDB,
Greenplum, RisingWave, YugabyteDB, Hologres, Doris, StarRocks, OceanBase)
silently inherited unverified aggregate SQL instead of the intended
"not supported on this database" error. Each now explicitly overrides
`_extended_aggregations` to `{}` until someone verifies it live.

Also fixes two smaller gaps the same review surfaced: MEDIAN was missing
from the MCP chart format validator's numeric-format branch, and
`get_metric_type_from_column`/`METRIC_MAP_TYPE` didn't recognize
STDDEV_SAMP/VAR_SAMP, so an all-null result column for either aggregate
fell back to STRING instead of NUMERIC.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bito-code-review

bito-code-review Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #2c7e2a

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/mcp_service/chart/validation/runtime/format_validator.py - 1
    • Missing test coverage for MEDIAN · Line 220-227
      The addition of "MEDIAN" to the statistical measures format list is correct. MEDIAN produces a decimal value similar to AVG and other sample statistics, so applying `,.2f` (two decimal places) is semantically appropriate. The change maintains consistency with the existing pattern used for STDDEV_SAMP, VAR_SAMP, and related aggregates.
Review Details
  • Files reviewed - 15 · Commit Range: f02ef22..cefee1b
    • superset/db_engine_specs/cockroachdb.py
    • superset/db_engine_specs/doris.py
    • superset/db_engine_specs/greenplum.py
    • superset/db_engine_specs/hana.py
    • superset/db_engine_specs/hologres.py
    • superset/db_engine_specs/netezza.py
    • superset/db_engine_specs/oceanbase.py
    • superset/db_engine_specs/risingwave.py
    • superset/db_engine_specs/snowflake.py
    • superset/db_engine_specs/starrocks.py
    • superset/db_engine_specs/vertica.py
    • superset/db_engine_specs/yugabytedb.py
    • superset/mcp_service/chart/validation/runtime/format_validator.py
    • superset/utils/core.py
    • tests/unit_tests/db_engine_specs/test_extended_aggregations_unverified.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:backend Requires changing the backend change:frontend Requires changing the frontend data:connect:duckdb Related to a specific database data:connect:mysql Related to MySQL data:connect:postgres Related to Postgres data:connect:redshift Related to Redshift doc Namespace | Anything related to documentation explore:metrics Related to metrics of Explore packages plugins preset-io size/XL viz:charts:pivot Related to the Pivot Table charts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants