@Override
    protected Boolean visitFieldReference(FieldReference node, Void context) {
      if (orderByScope.isPresent()) {
        return true;
      }

      FieldId fieldId =
          requireNonNull(columnReferences.get(NodeRef.of(node)), () -> "No field for " + node)
              .getFieldId();
      boolean inGroup = groupingFields.contains(fieldId);
      if (!inGroup) {
        Field field = sourceScope.getRelationType().getFieldByIndex(node.getFieldIndex());

        String column;
        if (!field.getName().isPresent()) {
          column = Integer.toString(node.getFieldIndex() + 1);
        } else if (field.getRelationAlias().isPresent()) {
          column = format("'%s.%s'", field.getRelationAlias().get(), field.getName().get());
        } else {
          column = "'" + field.getName().get() + "'";
        }

        throw new SemanticException(String.format("Column %s not in GROUP BY clause", column));
      }
      return inGroup;
    }
visitor returns true if all expressions are constant with respect to the group.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AggregationAnalyzer.java