You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MySQL STDDEV and VARIANCE are transpiled as sample instead of population #8626
Fully reproducible code snippet
In MySQL, STDDEV and VARIANCE are population functions (synonyms for STDDEV_POP and VAR_POP), but sqlglot treats them as the sample versions, so the result changes when transpiling to or from MySQL.
I looked into this — it reproduces, and it's actually a bit broader than the title suggests (both directions are affected, not just the one in the report).
Root cause:dialects/mysql.py has no explicit mapping for VARIANCE/STDDEV, so parsing falls through to the base parser.Parser.FUNCTIONS, which maps those literal names to the generic exp.Variance/exp.Stddev nodes. Those generic nodes are treated as sample semantics elsewhere in the codebase (e.g. postgres.py renders exp.Variance as VAR_SAMP). But per the MySQL docs, bare VARIANCE()/STDDEV() are documented synonyms for VAR_POP()/STDDEV_POP() — population, not sample:
>>>importsqlglot>>>sqlglot.transpile("SELECT VARIANCE(x), STDDEV(x) FROM t", read="mysql", write="postgres")
['SELECT VAR_SAMP(x), STDDEV(x) FROM t']
VAR_SAMP is just wrong (should be VAR_POP), and bare STDDEV in Postgres is also sample per the SQL standard, so that one's silently wrong too — same bug, no error raised either time.
The mirror-image bug exists too: writing a sample-semantics node to MySQL falls back to the bare name, which MySQL interprets as population:
>>>sqlglot.transpile("SELECT VAR_SAMP(x), STDDEV_SAMP(x) FROM t", read="mysql", write="mysql")
['SELECT VARIANCE(x), STDDEV_SAMP(x) FROM t']
VAR_SAMP(x) round-trips through MySQL as VARIANCE(x) — population. STDDEV_SAMP happens to survive because it has its own AST class with a default name MySQL also supports natively.
Fix (verified locally against the installed package, both directions, across mysql/postgres/duckdb/snowflake/bigquery):
After this, mysql -> mysql round-trips VARIANCE/STDDEV/VAR_SAMP/STDDEV_SAMP all correctly, and mysql -> {postgres,duckdb,snowflake,bigquery} all produce the right pop/sample function.
Happy to open a PR with this plus a test if that's useful — let me know.
Activity
thisismairaj commentedon Oct 14, 2026
I looked into this — it reproduces, and it's actually a bit broader than the title suggests (both directions are affected, not just the one in the report).
Root cause:
dialects/mysql.pyhas no explicit mapping forVARIANCE/STDDEV, so parsing falls through to the baseparser.Parser.FUNCTIONS, which maps those literal names to the genericexp.Variance/exp.Stddevnodes. Those generic nodes are treated as sample semantics elsewhere in the codebase (e.g.postgres.pyrendersexp.VarianceasVAR_SAMP). But per the MySQL docs, bareVARIANCE()/STDDEV()are documented synonyms forVAR_POP()/STDDEV_POP()— population, not sample:VAR_SAMPis just wrong (should beVAR_POP), and bareSTDDEVin Postgres is also sample per the SQL standard, so that one's silently wrong too — same bug, no error raised either time.The mirror-image bug exists too: writing a sample-semantics node to MySQL falls back to the bare name, which MySQL interprets as population:
VAR_SAMP(x)round-trips through MySQL asVARIANCE(x)— population.STDDEV_SAMPhappens to survive because it has its own AST class with a default name MySQL also supports natively.Fix (verified locally against the installed package, both directions, across mysql/postgres/duckdb/snowflake/bigquery):
In
MySQL.Parser.FUNCTIONS:In
MySQL.Generator.TRANSFORMS(mirrors the pattern already used by postgres/bigquery/duckdb/presto/spark2):After this,
mysql -> mysqlround-tripsVARIANCE/STDDEV/VAR_SAMP/STDDEV_SAMPall correctly, andmysql -> {postgres,duckdb,snowflake,bigquery}all produce the right pop/sample function.Happy to open a PR with this plus a test if that's useful — let me know.
fix(mssql,oracle): render bare Stddev as sample standard deviation (#…