没有聚集函数的GROUP BY子句将如何执行?

没有聚集函数的GROUP BY子句将如何执行?

在SQL中,GROUP BY子句常用来根据一个或多个列对表进行分组。通常,分组时还需要使用聚合函数,如SUM、AVG、COUNT等,来对每个组内的数据进行计算。但是,如果GROUP BY子句中没有聚合函数,又会发生怎样的情况呢?本文将对此进行详细讲解。

阅读更多:MySQL 教程

GROUP BY子句基本用法

在介绍不带聚合函数的GROUP BY子句的执行方式之前,我们先简单介绍一下GROUP BY子句的基本用法:

SELECT column_name, COUNT(*)
FROM table_name
GROUP BY column_name;

以上语句是一个典型的GROUP BY子句,它将根据column_name列对table_name表进行分组,然后统计每个组内的行数。在GROUP BY子句中,聚合函数通常都会作为SELECT语句的一部分使用。

不带聚合函数的GROUP BY子句

如果GROUP BY子句中不包含任何聚合函数,SQL引擎会采用以下方式执行:

  • 按照GROUP BY子句中指定的列进行分组;
  • 对于每个分组,保留其中的第一行数据,并将其作为结果集的一部分返回。

例如,假设我们有如下表students

+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | Tom  |    80 |
|  2 | Bob  |    90 |
|  3 | Jim  |    60 |
|  4 | Tim  |    70 |
|  5 | Ann  |    85 |
|  6 | Sam  |    95 |
+----+------+-------+

如果我们执行以下语句:

SELECT name, score
FROM students
GROUP BY name;

则结果集将是:

+------+-------+
| name | score |
+------+-------+
| Ann  |    85 |
| Bob  |    90 |
| Jim  |    60 |
| Sam  |    95 |
| Tim  |    70 |
| Tom  |    80 |
+------+-------+

在上面的例子中,我们选择了namescore两列,但GROUP BY子句只包含了name列,没有任何聚合函数。执行结果将会按照name列的值进行分组,然后对于分组中的每个值,只会选择其中的第一行数据(即相同name值的第一行数据)。最终结果集中只包含了6行数据,与原表的行数相等,说明没有进行聚合操作。

需要注意的是,SQL标准规定,在不带聚合函数的GROUP BY子句中,只允许出现SELECT列表中的列名、常量和表达式。如果GROUP BY子句中出现了其他列名,将会引发错误。

UNION ALL和ORDER BY

在不带聚合函数的GROUP BY子句中,还有两个和GROUP BY语句相关的操作:UNION ALL 和 ORDER BY 。

UNION ALL

在两个或多个表中,执行类似GROUP BY子句的操作,并将结果合并到一个结果集中。

假设我们有另一个表teacher,存放了各个科目的任课教师信息:

+------+-------+
| sub  | name  |
+------+-------+
| Math | John  |
| Math | Cathy |
| Math | Jack  |
| English | Mike |
| English | Susan|
+------+-------+

我们可以将studentsteacher的数据进行合并,并根据name字段进行分组,同时保留各自的科目信息:

SELECT name, 'student' AS type, score
FROMstudents
GROUP BY name 
UNION ALL 
SELECT name, 'teacher' AS type, NULL AS score 
FROM teacher 
GROUP BY name;

结果如下所示:

+-------+-----------+-------+
| name  |    type   | score |
+-------+-----------+-------+
| Ann   |  student  |    85 |
| Bob   |  student  |    90 |
| Cathy |  teacher  |  NULL |
| Jack  |  teacher  |  NULL |
| Jim   |  student  |    60 |
| John  |  teacher  |  NULL |
| Mike  |  teacher  |  NULL |
| Sam   |  student  |    95 |
| Susan |  teacher  |  NULL |
| Tim   |  student  |    70 |
| Tom   |  student  |    80 |
+-------+-----------+-------+

这里我们使用了UNION ALL 操作将studentsteacher两个表中的数据合并成了一个结果集,并使用了一个新的列type来区分数据是来自哪个表的。请注意,由于teacher表中没有score字段,因此我们需要在SELECT语句中为该列指定NULL值,以保证两个结果集的列数相同。

ORDER BY

在执行GROUP BY子句后,我们还可以对结果进行排序。例如,我们可以按照分数从高到低对结果进行排序:

SELECT name, score 
FROM students 
GROUP BY name 
ORDER BY score DESC;

结果如下所示:

+------+-------+
| name | score |
+------+-------+
| Sam  |    95 |
| Bob  |    90 |
| Ann  |    85 |
| Tom  |    80 |
| Tim  |    70 |
| Jim  |    60 |
+------+-------+

需要注意的是,由于在GROUP BY子句中没有使用任何聚合函数,因此排序操作实际上是基于每个分组中的第一行数据进行的。因此,结果集的排序方式可能无法满足我们的需求,是需要根据实际情况进行调整的。

结论

当GROUP BY子句中没有聚合函数时,SQL引擎会根据指定的列进行分组,并以每个分组中的第一行数据作为结果集的一部分返回。此外,还可以通过UNION ALL操作合并数据,并通过ORDER BY对结果进行排序。由于没有聚合函数的参与,因此GROUP BY子句查询结果应尽量避免重复、冗余数据的产生。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程