### Question:
PlanNodeStatsEstimateMath { public static PlanNodeStatsEstimate subtractSubsetStats(PlanNodeStatsEstimate superset, PlanNodeStatsEstimate subset) { if (superset.isOutputRowCountUnknown() || subset.isOutputRowCountUnknown()) { return PlanNodeStatsEstimate.unknown(); } double supersetRowCount = superset.getOutputRowCount(); double subsetRowCount = subset.getOutputRowCount(); double outputRowCount = max(supersetRowCount - subsetRowCount, 0); if (outputRowCount == 0) { return createZeroStats(superset); } PlanNodeStatsEstimate.Builder result = PlanNodeStatsEstimate.builder(); result.setOutputRowCount(outputRowCount); superset.getSymbolsWithKnownStatistics().forEach(symbol -> { SymbolStatsEstimate supersetSymbolStats = superset.getSymbolStatistics(symbol); SymbolStatsEstimate subsetSymbolStats = subset.getSymbolStatistics(symbol); SymbolStatsEstimate.Builder newSymbolStats = SymbolStatsEstimate.builder(); newSymbolStats.setAverageRowSize(supersetSymbolStats.getAverageRowSize()); double supersetNullsCount = supersetSymbolStats.getNullsFraction() * supersetRowCount; double subsetNullsCount = subsetSymbolStats.getNullsFraction() * subsetRowCount; double newNullsCount = max(supersetNullsCount - subsetNullsCount, 0); newSymbolStats.setNullsFraction(min(newNullsCount, outputRowCount) / outputRowCount); double supersetDistinctValues = supersetSymbolStats.getDistinctValuesCount(); double subsetDistinctValues = subsetSymbolStats.getDistinctValuesCount(); double newDistinctValuesCount; if (isNaN(supersetDistinctValues) || isNaN(subsetDistinctValues)) { newDistinctValuesCount = NaN; } else if (supersetDistinctValues == 0) { newDistinctValuesCount = 0; } else if (subsetDistinctValues == 0) { newDistinctValuesCount = supersetDistinctValues; } else { double supersetNonNullsCount = supersetRowCount - supersetNullsCount; double subsetNonNullsCount = subsetRowCount - subsetNullsCount; double supersetValuesPerDistinctValue = supersetNonNullsCount / supersetDistinctValues; double subsetValuesPerDistinctValue = subsetNonNullsCount / subsetDistinctValues; if (supersetValuesPerDistinctValue <= subsetValuesPerDistinctValue) { newDistinctValuesCount = max(supersetDistinctValues - subsetDistinctValues, 0); } else { newDistinctValuesCount = supersetDistinctValues; } } newSymbolStats.setDistinctValuesCount(newDistinctValuesCount); newSymbolStats.setLowValue(supersetSymbolStats.getLowValue()); newSymbolStats.setHighValue(supersetSymbolStats.getHighValue()); result.addSymbolStatistics(symbol, newSymbolStats.build()); }); return result.build(); } private  PlanNodeStatsEstimateMath(); static PlanNodeStatsEstimate subtractSubsetStats(PlanNodeStatsEstimate superset, PlanNodeStatsEstimate subset); static PlanNodeStatsEstimate capStats(PlanNodeStatsEstimate stats, PlanNodeStatsEstimate cap); static PlanNodeStatsEstimate addStatsAndSumDistinctValues(PlanNodeStatsEstimate left, PlanNodeStatsEstimate right); static PlanNodeStatsEstimate addStatsAndMaxDistinctValues(PlanNodeStatsEstimate left, PlanNodeStatsEstimate right); static PlanNodeStatsEstimate addStatsAndCollapseDistinctValues(PlanNodeStatsEstimate left, PlanNodeStatsEstimate right);  }### Answer:
@Test public void testSubtractRowCount() { PlanNodeStatsEstimate unknownStats = statistics(NaN, NaN, NaN, StatisticRange.empty()); PlanNodeStatsEstimate first = statistics(40, NaN, NaN, StatisticRange.empty()); PlanNodeStatsEstimate second = statistics(10, NaN, NaN, StatisticRange.empty()); assertEquals(subtractSubsetStats(unknownStats, unknownStats), PlanNodeStatsEstimate.unknown()); assertEquals(subtractSubsetStats(first, unknownStats), PlanNodeStatsEstimate.unknown()); assertEquals(subtractSubsetStats(unknownStats, second), PlanNodeStatsEstimate.unknown()); assertEquals(subtractSubsetStats(first, second).getOutputRowCount(), 30.0); }