private RelNode createCount(Aggregate aggr, List<List<Integer>> argList,
      List<List<Integer>> cleanArgList, Map<Integer, Integer> map,
      ImmutableBitSet originalGroupSet, ImmutableBitSet newGroupSet) throws CalciteSemanticException {
    final List<RexNode> originalInputRefs = aggr.getRowType().getFieldList()
        .stream()
        .map(input -> new RexInputRef(input.getIndex(), input.getType()))
        .collect(Collectors.toList());
    final List<RexNode> gbChildProjLst = Lists.newArrayList();
    // for singular arg, count should not include null
    // e.g., count(case when i=1 and department_id is not null then 1 else null end) as c0,
    // for non-singular args, count can include null, i.e. (,) is counted as 1
    for (List<Integer> list : cleanArgList) {
      RexNode condition = rexBuilder.makeCall(
          SqlStdOperatorTable.EQUALS,
          originalInputRefs.get(originalInputRefs.size() - 1),
          rexBuilder.makeExactLiteral(
              new BigDecimal(
                  getGroupingIdValue(list, originalGroupSet, newGroupSet, aggr.getGroupCount()))));
      if (list.size() == 1) {
        int pos = list.get(0);
        RexNode notNull = rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL,
            originalInputRefs.get(pos));
        condition = rexBuilder.makeCall(SqlStdOperatorTable.AND, condition, notNull);
      }
      RexNode caseExpr1 = rexBuilder.makeExactLiteral(BigDecimal.ONE);
      RexNode caseExpr2 = rexBuilder.makeNullLiteral(caseExpr1.getType());
      RexNode when = rexBuilder.makeCall(SqlStdOperatorTable.CASE, condition,
          caseExpr1, caseExpr2);
      gbChildProjLst.add(when);
    }

    for (int pos : originalGroupSet) {
      gbChildProjLst.add(originalInputRefs.get(newGroupSet.indexOf(pos)));
    }

    // create the project before GB
    RelNode gbInputRel = HiveProject.create(aggr, gbChildProjLst, null);

    // create the aggregate
    List<AggregateCall> aggregateCalls = Lists.newArrayList();
    RelDataType aggFnRetType = TypeConverter.convert(TypeInfoFactory.longTypeInfo,
        cluster.getTypeFactory());
    for (int i = 0; i < cleanArgList.size(); i++) {
      AggregateCall aggregateCall = HiveCalciteUtil.createSingleArgAggCall("count", cluster,
          TypeInfoFactory.longTypeInfo, i, aggFnRetType);
      aggregateCalls.add(aggregateCall);
    }
    ImmutableBitSet groupSet =
        ImmutableBitSet.range(cleanArgList.size(), cleanArgList.size() + originalGroupSet.cardinality());
    Aggregate aggregate = new HiveAggregate(cluster, cluster.traitSetOf(HiveRelNode.CONVENTION), gbInputRel,
        groupSet, null, aggregateCalls);

    // create the project after GB. For those repeated values, e.g., select
    // count(distinct x, y), count(distinct y, x), we find the correct mapping.
    if (map.isEmpty()) {
      return aggregate;
    } else {
      final List<RexNode> originalAggrRefs = aggregate.getRowType().getFieldList()
          .stream()
          .map(input -> new RexInputRef(input.getIndex(), input.getType()))
          .collect(Collectors.toList());
      final List<RexNode> projLst = Lists.newArrayList();
      int index = 0;
      for (int i = 0; i < groupSet.cardinality(); i++) {
        projLst.add(originalAggrRefs.get(index++));
      }
      for (int i = 0; i < argList.size(); i++) {
        if (map.containsKey(i)) {
          projLst.add(originalAggrRefs.get(map.get(i)));
        } else {
          projLst.add(originalAggrRefs.get(index++));
        }
      }
      return HiveProject.create(aggregate, projLst, null);
    }
  }
@param aggr: the original aggregate
@param argList: the original argList in aggregate
@param cleanArgList: the new argList without duplicates
@param map: the mapping from the original argList to the new argList
@param newGroupSet: the sorted positions of groupset
@return
@throws CalciteSemanticException
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveExpandDistinctAggregatesRule.java