prestodb/presto · error · SemanticException

NON_NUMERIC_SAMPLE_PERCENTAGE

NON_NUMERIC_SAMPLE_PERCENTAGE

Error message

Sample percentage cannot contain column references

What it means

TABLESAMPLE's sample percentage must be a constant expression; Presto extracts column references from the sample percentage expression and throws NON_NUMERIC_SAMPLE_PERCENTAGE if any are found. Allowing column references would make the sample ratio row-dependent, which the sampling implementation does not support.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:3172

                    .map(Field::getName)
                    .filter(Optional::isPresent)
                    .map(Optional::get)
                    // field names are resolved case-insensitive
                    .map(name -> name.toLowerCase(ENGLISH))
                    .forEach(name -> {
                        if (!names.add(name)) {
                            throw new SemanticException(DUPLICATE_COLUMN_NAME, relation.getRelation(), "Duplicate name of table function proper column: " + name);
                        }
                    });

            return new RelationType(fields);
        }

        @Override
        protected Scope visitSampledRelation(SampledRelation relation, Optional<Scope> scope)
        {
            if (!VariablesExtractor.extractNames(relation.getSamplePercentage(), analysis.getColumnReferences()).isEmpty()) {
                throw new SemanticException(NON_NUMERIC_SAMPLE_PERCENTAGE, relation.getSamplePercentage(), "Sample percentage cannot contain column references");
            }

            Map<NodeRef<Expression>, Type> expressionTypes = getExpressionTypes(
                    session,
                    metadata,
                    sqlParser,
                    TypeProvider.empty(),
                    relation.getSamplePercentage(),
                    analysis.getParameters(),
                    warningCollector,
                    analysis.isDescribe());
            ExpressionInterpreter samplePercentageEval = expressionOptimizer(relation.getSamplePercentage(), metadata, session, expressionTypes);

            Object samplePercentageObject = samplePercentageEval.optimize(symbol -> {
                throw new SemanticException(NON_NUMERIC_SAMPLE_PERCENTAGE, relation.getSamplePercentage(), "Sample percentage cannot contain column references");
            });
            try {
                samplePercentageObject = evaluateConstantExpression(relation.getSamplePercentage(), DOUBLE, metadata, session,

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use a literal numeric percentage, e.g. TABLESAMPLE BERNOULLI (10)
  2. Inline the desired value as a constant before running the query
  3. Use a session-level parameter substituted at query construction time
  4. If row-dependent sampling is needed, implement it with rand() <= ratio in a WHERE clause instead

Example fix

-- before
SELECT * FROM t TABLESAMPLE BERNOULLI (pct)
-- after
SELECT * FROM t TABLESAMPLE BERNOULLI (10)
Defensive patterns

Strategy: validation

Validate before calling

// sample percentage must be column-free before sending SQL
Set<NodeRef<Expression>> cols = VariablesExtractor.extractNames(samplePctExpr, analysisRefs);
if (!cols.isEmpty()) throw new IllegalArgumentException("sample percentage must be constant");

Type guard

boolean isLiteralPercentage(Expression e) {
    return e instanceof DoubleLiteral || e instanceof LongLiteral || e instanceof DecimalLiteral;
}

Try / catch

try {
    return engine.execute(sql);
} catch (SemanticException e) {
    if (e.getCode() == SemanticErrorCode.NON_NUMERIC_SAMPLE_PERCENTAGE) {
        sql = replaceSamplePctWithLiteral(sql, fixedPct); // retry with constant
    } else { throw e; }
}

Prevention

When it happens

Trigger: SELECT * FROM t TABLESAMPLE BERNOULLI (pct) where pct is a column of t; referencing any column (even from another table) inside the sample percentage expression.

Common situations: Trying to parameterize sample rate per row; storing sample sizes in a config table and referencing it in the query; misunderstanding that the percentage must be a literal/constant.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/a75dae9e51e01d91. Report an issue: GitHub.