private static SelectOperator mergeSelectOps(Operator<?> parent, List<SelectOperator> selectOperators) {
    List<String> colNames = new ArrayList<>();
    List<ExprNodeDesc> colDescs = new ArrayList<>();
    List<ColumnInfo> columnInfos = new ArrayList<>();
    Map<String, ExprNodeDesc> selectColumnExprMap = new HashMap<>();
    for (SelectOperator sel : selectOperators) {
      checkState(sel.getConf().getColList().size() == 1);
      ExprNodeDesc col = sel.getConf().getColList().get(0);
      String colName = HiveConf.getColumnInternalName(colDescs.size());
      colNames.add(colName);
      columnInfos.add(new ColumnInfo(colName, col.getTypeInfo(), "", false));
      colDescs.add(col);
      selectColumnExprMap.put(colName, col);
    }
    ExprNodeDesc hashExp = ExprNodeDescUtils.murmurHash(colDescs);
    String hashName = HiveConf.getColumnInternalName(colDescs.size() + 1);
    colNames.add(hashName);
    columnInfos.add(new ColumnInfo(hashName, hashExp.getTypeInfo(), "", false));
    // The n-1 columns in selDescs are used as parameters to min/max aggregations
    List<ExprNodeDesc> selDescs = new ArrayList<>(colDescs);
    // The nth column in selDescs is used as parameter to the bloom_filter aggregation
    selDescs.add(hashExp);

    SelectDesc select = new SelectDesc(selDescs, colNames);
    SelectOperator selectOp =
        (SelectOperator) OperatorFactory.getAndMakeChild(select, new RowSchema(columnInfos), parent);
    selectOp.setColumnExprMap(selectColumnExprMap);
    return selectOp;
  }
Merges multiple select operators in a single one appending an additional column that is the hash of all the others.

<pre>
Input: SEL[fname], SEL[lname], SEL[age]
Output: SEL[fname, lname, age, hash(fname, lname, age)]
</pre>
ql/src/java/org/apache/hadoop/hive/ql/optimizer/SemiJoinReductionMerge.java