@Override
  public Result apply(AggregationNode aggregation, Captures captures, Context context) {
    List<Set<Expression>> argumentSets =
        extractArgumentSets(aggregation).collect(Collectors.toList());

    Set<Symbol> symbols =
        Iterables.getOnlyElement(argumentSets).stream()
            .map(Symbol::from)
            .collect(Collectors.toSet());

    return Result.ofPlanNode(
        AggregationNode.builderFrom(aggregation)
            .setSource(
                singleAggregation(
                    context.getIdAllocator().genPlanNodeId(),
                    aggregation.getChild(),
                    ImmutableMap.of(),
                    singleGroupingSet(
                        ImmutableList.<Symbol>builder()
                            // make sure date_bin is in the last of GroupingKeys
                            .addAll(symbols)
                            .addAll(aggregation.getGroupingKeys())
                            .build())))
            .setAggregations(
                // remove DISTINCT flag from function calls
                aggregation.getAggregations().entrySet().stream()
                    .collect(
                        Collectors.toMap(Map.Entry::getKey, e -> removeDistinct(e.getValue()))))
            .setPreGroupedSymbols(ImmutableList.of())
            .build());
  }
Implements distinct aggregations with similar inputs by transforming plans of the following
shape:

<pre>
- Aggregation
       GROUP BY (k)
       F1(DISTINCT s0, s1, ...),
       F2(DISTINCT s0, s1, ...),
    - X
</pre>

into

<pre>
- Aggregation
         GROUP BY (k)
         F1(s0, s1, ...)
         F2(s0, s1, ...)
     - Aggregation
            GROUP BY (k, s0, s1, ...)
         - X
</pre>

<p>Assumes s0, s1, ... are symbol references (i.e., complex expressions have been pre-projected)
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/SingleDistinctAggregationToGroupBy.java