diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 9351e0cd3b3..080cfd1bdb1 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1119,6 +1119,7 @@ inheritance_planner(PlannerInfo *root)
 	Query	   *parent_parse;
 	Bitmapset  *parent_relids = bms_make_singleton(top_parentRTindex);
 	PlannerInfo **parent_roots = NULL;
+	PlannerInfo *partition_root = NULL;
 
 	Assert(parse->commandType != CMD_INSERT);
 
@@ -1196,6 +1197,33 @@ inheritance_planner(PlannerInfo *root)
 		 * of the ModifyTable node, if one is needed at all.
 		 */
 		partitioned_relids = bms_make_singleton(top_parentRTindex);
+
+
+		/*
+		 * For partitioned tables, since we're able to determine the minimum
+		 * set of partitions required much more easily than what we can do
+		 * with an inheritance hierarchy, we invoke the grouping_planner on
+		 * the entire given query in order to determine the minimum set of
+		 * partitions which will be required below.  This may mean that we
+		 * invoke the grouping planner far fewer times, as otherwise we'd
+		 * have to invoke it once for each partition.
+		 */
+
+		/*
+		 * Since the planner tends to scribble on the parse, we must make a
+		 * copy of it.  We also must make copies of the PlannerInfo and
+		 * PlannerGlobal since these will also be modified from the call to
+		 * grouping_planner.
+		 */
+		partition_root = makeNode(PlannerInfo);
+		partition_root->glob = makeNode(PlannerGlobal);
+
+		memcpy(partition_root, root, sizeof(PlannerInfo));
+		memcpy(partition_root->glob, root->glob, sizeof(PlannerGlobal));
+
+		partition_root->parse = copyObject(partition_root->parse);
+
+		grouping_planner(partition_root, true, 0.0 /* retrieve all tuples */ );
 	}
 
 	/*
@@ -1226,6 +1254,21 @@ inheritance_planner(PlannerInfo *root)
 		if (!bms_is_member(appinfo->parent_relid, parent_relids))
 			continue;
 
+		/*
+		 * If the target rel is a partitioned table then skip any child
+		 * partitions which were found to be dummies by the grouping_planner
+		 * call performed above.
+		 */
+		if (partition_root)
+		{
+			RelOptInfo *rel;
+
+			rel = find_base_rel(partition_root, appinfo->child_relid);
+
+			if (IS_DUMMY_REL(rel))
+				continue;
+		}
+
 		/*
 		 * expand_inherited_rtentry() always processes a parent before any of
 		 * that parent's children, so the parent_root for this relation should
@@ -1486,6 +1529,14 @@ inheritance_planner(PlannerInfo *root)
 	/* Result path must go into outer query's FINAL upperrel */
 	final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
 
+	if (partition_root)
+	{
+		RelOptInfo *partrel;
+
+		partrel = find_base_rel(partition_root, nominalRelation);
+		final_rel->baserestrictinfo = partrel->baserestrictinfo;
+	}
+
 	/*
 	 * We don't currently worry about setting final_rel's consider_parallel
 	 * flag in this case, nor about allowing FDWs or create_upper_paths_hook
