diff --git a/src/adql/db/DBChecker.java b/src/adql/db/DBChecker.java
index 297de8216aa8080cf02804651df7103d2dfcfaaf..8e6b8ae03c53b2b16b8fa766677f8eabb5cf17d9 100644
--- a/src/adql/db/DBChecker.java
+++ b/src/adql/db/DBChecker.java
@@ -97,7 +97,7 @@ import adql.search.SimpleSearchHandler;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.4 (03/2017)
+ * @version 1.4 (04/2017)
  */
 public class DBChecker implements QueryChecker {
 
@@ -632,7 +632,7 @@ public class DBChecker implements QueryChecker {
 
 		// Check the correctness of all column references (= references to selected columns):
 		/* Note: no need to provide the father tables when resolving column references,
-		 *       because no father column can be used in ORDER BY and/or GROUP BY. */
+		 *       because no father column can be used in ORDER BY. */
 		sHandler = new SearchColReferenceHandler();
 		sHandler.search(query);
 		ClauseSelect select = query.getSelect();
diff --git a/src/adql/parser/ADQLParser.java b/src/adql/parser/ADQLParser.java
index 8da4035a8a208f469f85d922c4ea11c7d6642383..ce4f24d3bb90e57a924248e56ff015d16dcfa4e9 100644
--- a/src/adql/parser/ADQLParser.java
+++ b/src/adql/parser/ADQLParser.java
@@ -16,7 +16,6 @@ import adql.query.ADQLQuery;
 import adql.query.ClauseADQL;
 import adql.query.ClauseConstraints;
 import adql.query.ClauseSelect;
-import adql.query.ColumnReference;
 import adql.query.SelectAllColumns;
 import adql.query.SelectItem;
 import adql.query.TextPosition;
@@ -889,11 +888,11 @@ public class ADQLParser implements ADQLParserConstants {
 	final public void GroupBy() throws ParseException{
 		trace_call("GroupBy");
 		try{
-			ClauseADQL<ColumnReference> groupBy = query.getGroupBy();
-			ColumnReference colRef = null;
+			ClauseADQL<ADQLColumn> groupBy = query.getGroupBy();
+			ADQLColumn colRef = null;
 			Token start;
 			start = jj_consume_token(GROUP_BY);
-			colRef = ColumnRef();
+			colRef = Column();
 			groupBy.add(colRef);
 			label_3: while(true){
 				switch((jj_ntk == -1) ? jj_ntk_f() : jj_ntk){
@@ -906,7 +905,7 @@ public class ADQLParser implements ADQLParserConstants {
 						break label_3;
 				}
 				jj_consume_token(COMMA);
-				colRef = ColumnRef();
+				colRef = Column();
 				groupBy.add(colRef);
 			}
 			groupBy.setPosition(new TextPosition(start.beginLine, start.beginColumn, colRef.getPosition().endLine, colRef.getPosition().endColumn));
@@ -1093,28 +1092,6 @@ public class ADQLParser implements ADQLParserConstants {
 		}
 	}
 
-	final public ColumnReference ColumnRef() throws ParseException{
-		trace_call("ColumnRef");
-		try{
-			IdentifierItems identifiers = null;
-			identifiers = ColumnName();
-			try{
-				{
-					if ("" != null)
-						return queryFactory.createColRef(identifiers);
-				}
-			}catch(Exception ex){
-				{
-					if (true)
-						throw generateParseException(ex);
-				}
-			}
-			throw new Error("Missing return statement in function");
-		}finally{
-			trace_return("ColumnRef");
-		}
-	}
-
 	final public ADQLOrder OrderItem() throws ParseException{
 		trace_call("OrderItem");
 		try{
@@ -3935,6 +3912,72 @@ public class ADQLParser implements ADQLParserConstants {
 		}
 	}
 
+	private boolean jj_3R_59(){
+		if (jj_3R_24())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_58(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_42())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_57(){
+		if (jj_3R_27())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_124(){
+		if (jj_scan_token(CIRCLE))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_134())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_135())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_101())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_44(){
+		if (jj_scan_token(SELECT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_56(){
+		if (jj_3R_101())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_123(){
+		if (jj_scan_token(CENTROID))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_113())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
 	private boolean jj_3R_117(){
 		if (jj_scan_token(LEFT_PAR))
 			return true;
@@ -3945,6 +3988,14 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
+	private boolean jj_3R_16(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_31())
+			return true;
+		return false;
+	}
+
 	private boolean jj_3R_122(){
 		if (jj_scan_token(BOX))
 			return true;
@@ -4004,12 +4055,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_44(){
-		if (jj_scan_token(SELECT))
-			return true;
-		return false;
-	}
-
 	private boolean jj_3R_115(){
 		if (jj_3R_22())
 			return true;
@@ -4034,14 +4079,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_16(){
-		if (jj_scan_token(LEFT_PAR))
-			return true;
-		if (jj_3R_31())
-			return true;
-		return false;
-	}
-
 	private boolean jj_3R_102(){
 		Token xsp;
 		xsp = jj_scanpos;
@@ -4166,6 +4203,12 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
+	private boolean jj_3R_31(){
+		if (jj_3R_44())
+			return true;
+		return false;
+	}
+
 	private boolean jj_3R_100(){
 		if (jj_scan_token(DISTANCE))
 			return true;
@@ -4237,12 +4280,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_31(){
-		if (jj_3R_44())
-			return true;
-		return false;
-	}
-
 	private boolean jj_3R_104(){
 		if (jj_scan_token(RIGHT))
 			return true;
@@ -4639,6 +4676,16 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
+	private boolean jj_3R_36(){
+		if (jj_3R_14())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_52())
+			jj_scanpos = xsp;
+		return false;
+	}
+
 	private boolean jj_3R_114(){
 		if (jj_3R_42())
 			return true;
@@ -4653,44 +4700,34 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_142(){
-		if (jj_scan_token(COMMA))
+	private boolean jj_3R_119(){
+		if (jj_scan_token(DOT))
 			return true;
-		if (jj_3R_152())
+		if (jj_3R_14())
 			return true;
 		return false;
 	}
 
-	private boolean jj_3R_141(){
-		if (jj_scan_token(COMMA))
-			return true;
-		if (jj_3R_152())
+	private boolean jj_3R_118(){
+		if (jj_scan_token(DOT))
 			return true;
-		return false;
-	}
-
-	private boolean jj_3R_36(){
 		if (jj_3R_14())
 			return true;
-		Token xsp;
-		xsp = jj_scanpos;
-		if (jj_3R_52())
-			jj_scanpos = xsp;
 		return false;
 	}
 
-	private boolean jj_3R_119(){
-		if (jj_scan_token(DOT))
+	private boolean jj_3R_142(){
+		if (jj_scan_token(COMMA))
 			return true;
-		if (jj_3R_14())
+		if (jj_3R_152())
 			return true;
 		return false;
 	}
 
-	private boolean jj_3R_118(){
-		if (jj_scan_token(DOT))
+	private boolean jj_3R_141(){
+		if (jj_scan_token(COMMA))
 			return true;
-		if (jj_3R_14())
+		if (jj_3R_152())
 			return true;
 		return false;
 	}
@@ -4720,6 +4757,17 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
+	private boolean jj_3R_14(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_28()){
+			jj_scanpos = xsp;
+			if (jj_3R_29())
+				return true;
+		}
+		return false;
+	}
+
 	private boolean jj_3R_131(){
 		if (jj_3R_102())
 			return true;
@@ -4746,17 +4794,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_14(){
-		Token xsp;
-		xsp = jj_scanpos;
-		if (jj_3R_28()){
-			jj_scanpos = xsp;
-			if (jj_3R_29())
-				return true;
-		}
-		return false;
-	}
-
 	private boolean jj_3R_130(){
 		if (jj_3R_21())
 			return true;
@@ -5145,6 +5182,14 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
+	private boolean jj_3R_30(){
+		if (jj_3R_14())
+			return true;
+		if (jj_scan_token(DOT))
+			return true;
+		return false;
+	}
+
 	private boolean jj_3R_27(){
 		if (jj_3R_35())
 			return true;
@@ -5227,16 +5272,20 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_39(){
-		if (jj_3R_54())
+	private boolean jj_3R_15(){
+		if (jj_3R_14())
 			return true;
+		if (jj_scan_token(DOT))
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_30())
+			jj_scanpos = xsp;
 		return false;
 	}
 
-	private boolean jj_3R_30(){
-		if (jj_3R_14())
-			return true;
-		if (jj_scan_token(DOT))
+	private boolean jj_3R_39(){
+		if (jj_3R_54())
 			return true;
 		return false;
 	}
@@ -5281,18 +5330,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_15(){
-		if (jj_3R_14())
-			return true;
-		if (jj_scan_token(DOT))
-			return true;
-		Token xsp;
-		xsp = jj_scanpos;
-		if (jj_3R_30())
-			jj_scanpos = xsp;
-		return false;
-	}
-
 	private boolean jj_3R_133(){
 		Token xsp;
 		xsp = jj_scanpos;
@@ -5352,6 +5389,20 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
+	private boolean jj_3_1(){
+		if (jj_3R_14())
+			return true;
+		if (jj_scan_token(DOT))
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_15())
+			jj_scanpos = xsp;
+		if (jj_scan_token(ASTERISK))
+			return true;
+		return false;
+	}
+
 	private boolean jj_3R_19(){
 		if (jj_3R_34())
 			return true;
@@ -5430,20 +5481,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3_1(){
-		if (jj_3R_14())
-			return true;
-		if (jj_scan_token(DOT))
-			return true;
-		Token xsp;
-		xsp = jj_scanpos;
-		if (jj_3R_15())
-			jj_scanpos = xsp;
-		if (jj_scan_token(ASTERISK))
-			return true;
-		return false;
-	}
-
 	private boolean jj_3_9(){
 		if (jj_3R_22())
 			return true;
@@ -5575,66 +5612,6 @@ public class ADQLParser implements ADQLParserConstants {
 		return false;
 	}
 
-	private boolean jj_3R_59(){
-		if (jj_3R_24())
-			return true;
-		return false;
-	}
-
-	private boolean jj_3R_58(){
-		if (jj_scan_token(LEFT_PAR))
-			return true;
-		if (jj_3R_42())
-			return true;
-		if (jj_scan_token(RIGHT_PAR))
-			return true;
-		return false;
-	}
-
-	private boolean jj_3R_57(){
-		if (jj_3R_27())
-			return true;
-		return false;
-	}
-
-	private boolean jj_3R_124(){
-		if (jj_scan_token(CIRCLE))
-			return true;
-		if (jj_scan_token(LEFT_PAR))
-			return true;
-		if (jj_3R_134())
-			return true;
-		if (jj_scan_token(COMMA))
-			return true;
-		if (jj_3R_135())
-			return true;
-		if (jj_scan_token(COMMA))
-			return true;
-		if (jj_3R_101())
-			return true;
-		if (jj_scan_token(RIGHT_PAR))
-			return true;
-		return false;
-	}
-
-	private boolean jj_3R_56(){
-		if (jj_3R_101())
-			return true;
-		return false;
-	}
-
-	private boolean jj_3R_123(){
-		if (jj_scan_token(CENTROID))
-			return true;
-		if (jj_scan_token(LEFT_PAR))
-			return true;
-		if (jj_3R_113())
-			return true;
-		if (jj_scan_token(RIGHT_PAR))
-			return true;
-		return false;
-	}
-
 	/** Generated Token Manager. */
 	public ADQLParserTokenManager token_source;
 	SimpleCharStream jj_input_stream;
diff --git a/src/adql/parser/adqlGrammar.jj b/src/adql/parser/adqlGrammar.jj
index 857997bfeddd3433d84857ec80cf3dc33f14b200..a4d2cb4bddd98546b95325fc5ab742d2f277183d 100644
--- a/src/adql/parser/adqlGrammar.jj
+++ b/src/adql/parser/adqlGrammar.jj
@@ -841,9 +841,9 @@ void Where(): {ClauseConstraints where = query.getWhere(); ADQLConstraint condit
 	}
 }
 
-void GroupBy(): {ClauseADQL<ColumnReference> groupBy = query.getGroupBy(); ColumnReference colRef = null; Token start;} {
-	start=<GROUP_BY> colRef=ColumnRef() { groupBy.add(colRef); }
-	( <COMMA> colRef=ColumnRef() { groupBy.add(colRef); } )*
+void GroupBy(): {ClauseADQL<ADQLColumn> groupBy = query.getGroupBy(); ADQLColumn colRef = null; Token start;} {
+	start=<GROUP_BY> colRef=Column() { groupBy.add(colRef); }
+	( <COMMA> colRef=Column() { groupBy.add(colRef); } )*
 	{ groupBy.setPosition(new TextPosition(start.beginLine, start.beginColumn, colRef.getPosition().endLine, colRef.getPosition().endColumn)); }
 }
 
@@ -916,17 +916,6 @@ ADQLColumn Column(): {IdentifierItems identifiers;} {
 	}
 }
 
-ColumnReference ColumnRef(): {IdentifierItems identifiers = null;}{
-	identifiers=ColumnName()
-	{
-		try{
-			return queryFactory.createColRef(identifiers);
-		}catch(Exception ex){
-			throw generateParseException(ex);
-		}
-	}
-}
-
 ADQLOrder OrderItem(): {IdentifierItem identifier = null; Token ind = null, desc = null;}{
 	(identifier=Identifier() | ind=<UNSIGNED_INTEGER>) (<ASC> | desc=<DESC>)?
 	{
diff --git a/src/adql/query/ADQLQuery.java b/src/adql/query/ADQLQuery.java
index dd0a9b9580967a229ad9ecd731f54b865ef02df5..bd0d19cbd8042e35ada28021d74edffe1670fee9 100644
--- a/src/adql/query/ADQLQuery.java
+++ b/src/adql/query/ADQLQuery.java
@@ -47,7 +47,7 @@ import adql.search.ISearchHandler;
  * <p>The resulting object of the {@link ADQLParser} is an object of this class.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.4 (02/2017)
+ * @version 1.4 (04/2017)
  */
 public class ADQLQuery implements ADQLObject {
 
@@ -61,7 +61,7 @@ public class ADQLQuery implements ADQLObject {
 	private ClauseConstraints where;
 
 	/** The ADQL clause GROUP BY. */
-	private ClauseADQL<ColumnReference> groupBy;
+	private ClauseADQL<ADQLColumn> groupBy;
 
 	/** The ADQL clause HAVING. */
 	private ClauseConstraints having;
@@ -80,7 +80,7 @@ public class ADQLQuery implements ADQLObject {
 		select = new ClauseSelect();
 		from = null;
 		where = new ClauseConstraints("WHERE");
-		groupBy = new ClauseADQL<ColumnReference>("GROUP BY");
+		groupBy = new ClauseADQL<ADQLColumn>("GROUP BY");
 		having = new ClauseConstraints("HAVING");
 		orderBy = new ClauseADQL<ADQLOrder>("ORDER BY");
 	}
@@ -96,7 +96,7 @@ public class ADQLQuery implements ADQLObject {
 		select = (ClauseSelect)toCopy.select.getCopy();
 		from = (FromContent)toCopy.from.getCopy();
 		where = (ClauseConstraints)toCopy.where.getCopy();
-		groupBy = (ClauseADQL<ColumnReference>)toCopy.groupBy.getCopy();
+		groupBy = (ClauseADQL<ADQLColumn>)toCopy.groupBy.getCopy();
 		having = (ClauseConstraints)toCopy.having.getCopy();
 		orderBy = (ClauseADQL<ADQLOrder>)toCopy.orderBy.getCopy();
 		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
@@ -201,7 +201,7 @@ public class ADQLQuery implements ADQLObject {
 	 * 
 	 * @return	Its GROUP BY clause.
 	 */
-	public final ClauseADQL<ColumnReference> getGroupBy(){
+	public final ClauseADQL<ADQLColumn> getGroupBy(){
 		return groupBy;
 	}
 
@@ -213,7 +213,7 @@ public class ADQLQuery implements ADQLObject {
 	 * @param newGroupBy				The new GROUP BY clause.
 	 * @throws NullPointerException		If the given GROUP BY clause is <i>null</i>.
 	 */
-	public void setGroupBy(ClauseADQL<ColumnReference> newGroupBy) throws NullPointerException{
+	public void setGroupBy(ClauseADQL<ADQLColumn> newGroupBy) throws NullPointerException{
 		if (newGroupBy == null)
 			groupBy.clear();
 		else
@@ -454,7 +454,7 @@ public class ADQLQuery implements ADQLObject {
 							break;
 						case 3:
 							if (replacer instanceof ClauseADQL)
-								groupBy = (ClauseADQL<ColumnReference>)replacer;
+								groupBy = (ClauseADQL<ADQLColumn>)replacer;
 							else
 								throw new UnsupportedOperationException("Impossible to replace a ClauseADQL (" + groupBy.toADQL() + ") by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 							break;
diff --git a/src/adql/query/ColumnReference.java b/src/adql/query/ColumnReference.java
index 3390e7a716bf975da31c15624fc55fa123d7ff65..78d41c2d54b7acedfab84d67932b3650db3ed09d 100644
--- a/src/adql/query/ColumnReference.java
+++ b/src/adql/query/ColumnReference.java
@@ -24,7 +24,7 @@ import adql.query.from.ADQLTable;
 import adql.query.operand.ADQLColumn;
 
 /**
- * Represents a reference to a selected column either by an index or by a name/alias.
+ * Represents a reference to a selected column either by an index or by a non-qualified column name/alias.
  * 
  * @author Gr&eacute;gory Mantelet (CDS)
  * @version 01/2012
@@ -94,6 +94,7 @@ public class ColumnReference implements ADQLObject {
 	 * 
 	 * @return	The position of this {@link ColumnReference}.
 	 */
+	@Override
 	public final TextPosition getPosition(){
 		return position;
 	}
@@ -235,18 +236,22 @@ public class ColumnReference implements ADQLObject {
 		this.adqlTable = adqlTable;
 	}
 
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new ColumnReference(this);
 	}
 
+	@Override
 	public String getName(){
 		return isIndex() ? (columnIndex + "") : columnName;
 	}
 
+	@Override
 	public final ADQLIterator adqlIterator(){
 		return new NullADQLIterator();
 	}
 
+	@Override
 	public String toADQL(){
 		return isIndex() ? ("" + columnIndex) : (isCaseSensitive() ? ("\"" + columnName + "\"") : columnName);
 	}
diff --git a/test/adql/db/TestDBChecker.java b/test/adql/db/TestDBChecker.java
index b0b184b24e6de05219daabef7ff3c8f101875b80..aec904dec03b4a1cffa1bb5371f5756eda8862c5 100644
--- a/test/adql/db/TestDBChecker.java
+++ b/test/adql/db/TestDBChecker.java
@@ -96,6 +96,22 @@ public class TestDBChecker {
 			assertEquals(expected[i], names[i]);
 	}
 
+	@Test
+	public void testGroupByWithQualifiedColName(){
+		ADQLParser parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0)));
+		try{
+			// Not qualified column name:
+			parser.parseQuery("SELECT colI, COUNT(*) AS cnt FROM foo GROUP BY colI");
+			// Qualified with the table name:
+			parser.parseQuery("SELECT foo.colI, COUNT(*) AS cnt FROM foo GROUP BY foo.colI");
+			// Qualified with the table alias:
+			parser.parseQuery("SELECT f.colI, COUNT(*) AS cnt FROM foo AS f GROUP BY f.colI");
+		}catch(ParseException pe){
+			pe.printStackTrace();
+			fail();
+		}
+	}
+
 	@Test
 	public void testQualifiedName(){
 		ADQLParser parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0)));