private void analyzeHaving(QuerySpecification node, Scope scope) {
      if (node.getHaving().isPresent()) {
        Expression predicate = node.getHaving().get();

        ExpressionAnalysis expressionAnalysis = analyzeExpression(predicate, scope);
        analysis.recordSubqueries(node, expressionAnalysis);

        Type predicateType = expressionAnalysis.getType(predicate);
        if (!predicateType.equals(BOOLEAN)) {
          throw new SemanticException(
              String.format(
                  "HAVING clause must evaluate to a boolean: actual type %s", predicateType));
        }

        analysis.setHaving(node, predicate);
      }
    }
Check if there is Columns function in expression, and verify they are same if there are multi
Column functions.

@param expression input expression
@return if there is Columns function in expression
@throws SemanticException if there are multi Columns functions but different
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java