diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index f980d52f2b0e72e2fbee05a4f094227dcc2aa367..92ea3b9bd9e4b54198c802e78cc11fdbb11988f1 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.51 2003/01/17 03:25:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.52 2003/04/03 18:04:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "optimizer/clauses.h"
 #include "optimizer/tlist.h"
+#include "optimizer/var.h"
 #include "parser/parse_agg.h"
 #include "parser/parsetree.h"
 
@@ -179,7 +180,9 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
 {
 	List	   *groupClauses = NIL;
 	bool		have_non_var_grouping = false;
-	List	   *tl;
+	List	   *lst;
+	bool		hasJoinRTEs;
+	Node	   *clause;
 
 	/* This should only be called if we found aggregates, GROUP, or HAVING */
 	Assert(pstate->p_hasAggs || qry->groupClause || qry->havingQual);
@@ -205,9 +208,9 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
 	 * repeated scans of the targetlist within the recursive routine...).
 	 * And detect whether any of the expressions aren't simple Vars.
 	 */
-	foreach(tl, qry->groupClause)
+	foreach(lst, qry->groupClause)
 	{
-		GroupClause *grpcl = lfirst(tl);
+		GroupClause *grpcl = (GroupClause *) lfirst(lst);
 		Node	   *expr;
 
 		expr = get_sortgroupclause_expr(grpcl, qry->targetList);
@@ -220,14 +223,40 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
 			have_non_var_grouping = true;
 	}
 
+	/*
+	 * If there are join alias vars involved, we have to flatten them
+	 * to the underlying vars, so that aliased and unaliased vars will be
+	 * correctly taken as equal.  We can skip the expense of doing this
+	 * if no rangetable entries are RTE_JOIN kind.
+	 */
+	hasJoinRTEs = false;
+	foreach(lst, pstate->p_rtable)
+	{
+		RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst);
+
+		if (rte->rtekind == RTE_JOIN)
+		{
+			hasJoinRTEs = true;
+			break;
+		}
+	}
+
+	if (hasJoinRTEs)
+		groupClauses = (List *) flatten_join_alias_vars(qry,
+														(Node *) groupClauses);
+
 	/*
 	 * Check the targetlist and HAVING clause for ungrouped variables.
 	 */
-	check_ungrouped_columns((Node *) qry->targetList, pstate,
-							groupClauses, have_non_var_grouping);
-	check_ungrouped_columns((Node *) qry->havingQual, pstate,
+	clause = (Node *) qry->targetList;
+	if (hasJoinRTEs)
+		clause = flatten_join_alias_vars(qry, clause);
+	check_ungrouped_columns(clause, pstate,
 							groupClauses, have_non_var_grouping);
 
-	/* Release the list storage (but not the pointed-to expressions!) */
-	freeList(groupClauses);
+	clause = (Node *) qry->havingQual;
+	if (hasJoinRTEs)
+		clause = flatten_join_alias_vars(qry, clause);
+	check_ungrouped_columns(clause, pstate,
+							groupClauses, have_non_var_grouping);
 }