private void pushdownThroughTopNKey(TopNKeyOperator topNKey) throws SemanticException {
    TopNKeyOperator parent = (TopNKeyOperator) topNKey.getParentOperators().get(0);
    if (hasSameTopNKeyDesc(parent, topNKey.getConf())) {
      LOG.debug("Removing {} above same operator: {}", topNKey.getName(), parent.getName());
      parent.removeChildAndAdoptItsChildren(topNKey);
      return;
    }

    TopNKeyDesc topNKeyDesc = topNKey.getConf();
    TopNKeyDesc parentTopNKeyDesc = parent.getConf();
    CommonKeyPrefix commonKeyPrefix = CommonKeyPrefix.map(
            topNKeyDesc.getKeyColumns(), topNKeyDesc.getColumnSortOrder(), topNKeyDesc.getNullOrder(),
            parentTopNKeyDesc.getKeyColumns(), parentTopNKeyDesc.getColumnSortOrder(),
            parentTopNKeyDesc.getNullOrder());

    if (topNKeyDesc.getTopN() == parentTopNKeyDesc.getTopN()) {
      if (topNKeyDesc.getKeyColumns().size() == commonKeyPrefix.size()) {
        // TNK keys are subset of the parent TNK keys
        pushdownThroughParent(topNKey);
        if (topNKey.getChildOperators().get(0).getType() == OperatorType.TOPNKEY) {
          LOG.debug("Removing {} since child {} supersedes it", parent.getName(), topNKey.getName());
          topNKey.getParentOperators().get(0).removeChildAndAdoptItsChildren(topNKey);
        }
      } else if (parentTopNKeyDesc.getKeyColumns().size() == commonKeyPrefix.size()) {
        // parent TNK keys are subset of TNK keys
        LOG.debug("Removing parent of {} since it supersedes", topNKey.getName());
        parent.getParentOperators().get(0).removeChildAndAdoptItsChildren(parent);
      }
    } else if (topNKeyDesc.getKeyColumns().size() == commonKeyPrefix.size() &&
            parentTopNKeyDesc.getKeyColumns().size() == commonKeyPrefix.size()) {
      if (topNKeyDesc.getTopN() > parentTopNKeyDesc.getTopN()) {
        LOG.debug("Removing {}. Parent {} has same keys but lower topN {} > {}",
                topNKey.getName(), parent.getName(), topNKeyDesc.getTopN(), parentTopNKeyDesc.getTopN());
        topNKey.getParentOperators().get(0).removeChildAndAdoptItsChildren(topNKey);
      } else {
        LOG.debug("Removing parent {}. {} has same keys but lower topN {} < {}",
                parent.getName(), topNKey.getName(), topNKeyDesc.getTopN(), parentTopNKeyDesc.getTopN());
        parent.getParentOperators().get(0).removeChildAndAdoptItsChildren(parent);
      }
    }
  }
Push through another Top N Key operator.
If the TNK operators are the same one of them will be removed. See {@link TopNKeyDesc#isSame}
else If expression in <code>topnKey</code> is a common prefix in it's parent TNK op and topN property is same
then <code>topnkey</code> could be pushed through parent.
If the Top N Key operator can not be pushed through this method tries to remove one of them:
- if topN property is the same and the keys of one of the operators are subset of the other then the operator
  can be removed
- if the keys are the same operator with higher topN value can be removed
@param topNKey TopNKey operator to push
@throws SemanticException when removeChildAndAdoptItsChildren was not successful
ql/src/java/org/apache/hadoop/hive/ql/optimizer/topnkey/TopNKeyPushdownProcessor.java