diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index a5424c9d24c..6834a3cb4c1 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -1424,6 +1424,37 @@ substitute_grouped_columns_mutator(Node *node,
 			return node;
 	}
 
+	/*
+	 * GROUP BY of a Const or Param refers to one targetlist entry.  Other
+	 * occurrences of the same value are not that column, so they must not
+	 * be replaced.
+	 */
+	if (context->sublevels_up == 0 &&
+		context->have_non_var_grouping &&
+		IsA(node, TargetEntry))
+	{
+		TargetEntry *tle = (TargetEntry *) node;
+		int			attnum = 0;
+
+		foreach(gl, context->groupClauses)
+		{
+			TargetEntry *grouptle = (TargetEntry *) lfirst(gl);
+
+			attnum++;
+			if (tle->ressortgroupref == grouptle->ressortgroupref &&
+				grouptle->ressortgroupref != 0 &&
+				(IsA(grouptle->expr, Const) || IsA(grouptle->expr, Param)))
+			{
+				TargetEntry *newtle = copyObject(tle);
+
+				newtle->expr = (Expr *) buildGroupedVar(attnum,
+														grouptle->ressortgroupref,
+														context);
+				return (Node *) newtle;
+			}
+		}
+	}
+
 	/*
 	 * If we have any GROUP BY items that are not simple Vars, check to see if
 	 * subexpression as a whole matches any GROUP BY item. We need to do this
@@ -1448,6 +1479,13 @@ substitute_grouped_columns_mutator(Node *node,
 			TargetEntry *tle = (TargetEntry *) lfirst(gl);
 
 			attnum++;
+
+			/*
+			 * Const and Param items were matched by targetlist entry above.
+			 */
+			if (IsA(tle->expr, Const) || IsA(tle->expr, Param))
+				continue;
+
 			if (equal(node, tle->expr))
 			{
 				/* acceptable, replace it with a GROUP Var */
@@ -1459,10 +1497,9 @@ substitute_grouped_columns_mutator(Node *node,
 	}
 
 	/*
-	 * Constants are always acceptable.  We have to do this after we checked
-	 * the subexpression as a whole for a match, because it is possible that
-	 * we have GROUP BY items that are constants, and the constants would
-	 * become not so constant after the grouping step.
+	 * Constants are always acceptable.  The grouped Const or Param itself
+	 * was replaced with its targetlist entry.  Any other constant is still
+	 * constant after grouping.
 	 */
 	if (IsA(node, Const) ||
 		IsA(node, Param))
diff --git a/src/test/regress/expected/groupingsets.out b/src/test/regress/expected/groupingsets.out
index 08d5ce3156d..93e8c3e7307 100644
--- a/src/test/regress/expected/groupingsets.out
+++ b/src/test/regress/expected/groupingsets.out
@@ -2762,4 +2762,44 @@ order by 1, 2;
  2 |   
 (6 rows)
 
+-- a grouped Const names one targetlist entry, not every equal Const
+select ARRAY[]::varchar(500)[] as a
+group by cast('true' as boolean);
+ a  
+----
+ {}
+(1 row)
+
+select ARRAY[]::char(1)[] as a
+group by cast(true as boolean);
+ a  
+----
+ {}
+(1 row)
+
+select ARRAY[]::varchar(500)[] as a
+group by cast(500 as int);
+ a  
+----
+ {}
+(1 row)
+
+select 'ab'::varchar(5) as v, true as t
+group by grouping sets ((cast(true as boolean)), ())
+order by t;
+ v  | t 
+----+---
+ ab | t
+ ab | 
+(2 rows)
+
+select ARRAY[]::varchar(5)[] as a, true as t
+group by grouping sets ((cast(true as boolean)), ())
+order by t;
+ a  | t 
+----+---
+ {} | t
+ {} | 
+(2 rows)
+
 -- end
diff --git a/src/test/regress/sql/groupingsets.sql b/src/test/regress/sql/groupingsets.sql
index c5d4ed2eb57..4afc20077a8 100644
--- a/src/test/regress/sql/groupingsets.sql
+++ b/src/test/regress/sql/groupingsets.sql
@@ -803,4 +803,22 @@ from (values (1, 1), (2, 2)) as t (a, b)
 group by rollup(a, ab)
 order by 1, 2;
 
+-- a grouped Const names one targetlist entry, not every equal Const
+select ARRAY[]::varchar(500)[] as a
+group by cast('true' as boolean);
+
+select ARRAY[]::char(1)[] as a
+group by cast(true as boolean);
+
+select ARRAY[]::varchar(500)[] as a
+group by cast(500 as int);
+
+select 'ab'::varchar(5) as v, true as t
+group by grouping sets ((cast(true as boolean)), ())
+order by t;
+
+select ARRAY[]::varchar(5)[] as a, true as t
+group by grouping sets ((cast(true as boolean)), ())
+order by t;
+
 -- end
