diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java index 445dce033a8778..67a82edbf53eef 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java @@ -286,10 +286,22 @@ protected boolean condition(Rule rule, Plan plan) { if (alias.child().anyMatch(expr -> expr instanceof AggregateFunction)) { continue; } - // NOTICE: must use unbound expressions, because we will bind them in binding group by expr. - childOutputsToExpr.putIfAbsent(alias.getName(), agg.getOutputExpressions().get(i).child(0)); + /* + Alias(x) has been bound by binding agg's output + we add x to childOutputsToExpr, so when binding group by exprs later, we can use x directly + and won't bind it again + select + p_cycle_time / (select max(p_cycle_time) from log_event_8) as 'x', + count(distinct case_id) as 'y' + from + log_event_8 + group by + x + */ + childOutputsToExpr.putIfAbsent(alias.getName(), output.get(i).child(0)); } + Set boundedGroupByExpressions = Sets.newHashSet(); List replacedGroupBy = agg.getGroupByExpressions().stream() .map(groupBy -> { if (groupBy instanceof UnboundSlot) { @@ -297,7 +309,9 @@ protected boolean condition(Rule rule, Plan plan) { if (unboundSlot.getNameParts().size() == 1) { String name = unboundSlot.getNameParts().get(0); if (childOutputsToExpr.containsKey(name)) { - return childOutputsToExpr.get(name); + Expression expression = childOutputsToExpr.get(name); + boundedGroupByExpressions.add(expression); + return expression; } } } @@ -330,16 +344,24 @@ protected boolean condition(Rule rule, Plan plan) { List groupBy = replacedGroupBy.stream() .map(expression -> { - Expression e = binder.bind(expression); - if (e instanceof UnboundSlot) { - return childBinder.bind(e); + if (boundedGroupByExpressions.contains(expression)) { + // expr has been bound by binding agg's output + return expression; + } else { + // bind slot for unbound exprs + Expression e = binder.bind(expression); + if (e instanceof UnboundSlot) { + return childBinder.bind(e); + } + return e; } - return e; }) .collect(Collectors.toList()); groupBy.forEach(expression -> checkBound(expression, ctx.root)); groupBy = groupBy.stream() - .map(expr -> bindFunction(expr, ctx.root, ctx.cascadesContext)) + // bind function for unbound exprs or return old expr if it's bound by binding agg's output + .map(expr -> boundedGroupByExpressions.contains(expr) ? expr + : bindFunction(expr, ctx.root, ctx.cascadesContext)) .collect(ImmutableList.toImmutableList()); checkIfOutputAliasNameDuplicatedForGroupBy(groupBy, output); return agg.withGroupByAndOutput(groupBy, output);