如何使用SQL系列 之 如何在SQL中使用GROUP BY和ORDER BY

引言

结构化查询语言(SQL)数据库可以跨多个表存储和管理大量数据。对于大型数据集,理解如何排序数据是很重要的,特别是对于分析结果集或为报告或外部通信组织数据。

SQL中有两个常用的用于数据排序的语句:GROUP BYORDER BYGROUP BY语句根据查询中指定的列对数据进行分组,并与聚集函数一起使用。ORDER BY允许您按字母或数字以及升序或降序组织结果集。

在本教程中,你将使用GROUP BYORDER BY语句在SQL中对查询结果进行排序。你还将练习在查询中实现聚合函数和WHERE子句,以便进一步对结果进行排序。

前期准备

为了学习本指南,你需要一台运行某种使用SQL的关系数据库管理系统(RDBMS)的计算机。

注意:请注意,许多RDBMS使用它们自己独特的SQL实现。虽然本教程中概述的命令适用于大多数RDBMS,但如果你在MySQL以外的系统上测试它们,确切的语法或输出可能会有所不同。

你还需要一个装载了一些示例数据的数据库和表,可以在其中练习使用相关命令。

连接到MySQL并设置一个示例数据库

如果SQL数据库系统运行在远程服务器上,请从本地设备SSH到服务器:

shell 复制代码
ssh sammy@your_server_ip

然后打开MySQL服务器提示符,将==sammy==替换为你的MySQL用户账户的名称:

shell 复制代码
mysql -u sammy -p

创建一个名为movieDB的数据库:

sql 复制代码
CREATE DATABASE movieDB;

如果数据库成功创建,您将收到这样的输出:

shell 复制代码
OutputQuery OK, 1 row affected (0.01 sec)

要选择movieDB数据库,运行以下USE语句:

shell 复制代码
USE movieDB;
shell 复制代码
OutputDatabase changed

选择数据库后,在其中创建一个表。在本教程的示例中,我们将创建一个表,用于存储本地电影院的放映信息。这个表将以下7个字段:

  • theater_id:存储每个剧院的展厅的int数据类型的值,并作为表的主键,这意味着这一列中的每个值都将作为其各自行的唯一标识符。

  • date:使用DATE数据类型来存储电影放映的年、月、日的特定日期。该数据类型遵循以下参数:4位数字表示年份,最多2位数字表示月和日(YYYY-MM-DD)。

  • time:用TIME数据类型以小时、分钟和秒(HH:MM:SS)表示电影的计划放映。

  • movie_name:使用varchar数据类型存储电影的名称,最多40个字符。

  • movie_genre:使用不超过30个字符的varchar数据类型,保存每部电影各自类型的信息。

  • guest_total:显示参加电影放映的总人数,数据类型为int

  • ticket_cost:使用decimal数据类型,精度为4,刻度为1,这意味着这一列的值可以有4位数字,小数点右侧有2位数字。这一列表示特定电影放映的票价。

通过运行下面的CREATE TABLE命令,创建一个名为movie_theater的表,其中包含这些列:

sql 复制代码
CREATE TABLE movie_theater (
theater_id int, 
date DATE,
time TIME, 
movie_name varchar(40),
movie_genre varchar(30),
guest_total int,
ticket_cost decimal(4,2),
PRIMARY KEY (theater_id)
); 

接下来,向空表中插入一些示例数据:

sql 复制代码
INSERT INTO movie_theater
(theater_id, date, time, movie_name, movie_genre, guest_total, ticket_cost)
VALUES
(1, '2022-05-27', '10:00:00', 'Top Gun Maverick', 'Action', 131, 18.00),
(2, '2022-05-27', '10:00:00', 'Downton Abbey A New Era', 'Drama', 90, 18.00),
(3, '2022-05-27', '10:00:00', 'Men', 'Horror', 100, 18.00),
(4, '2022-05-27', '10:00:00', 'The Bad Guys', 'Animation', 83, 18.00),
(5, '2022-05-28', '09:00:00', 'Top Gun Maverick', 'Action', 112, 8.00),
(6, '2022-05-28', '09:00:00', 'Downton Abbey A New Era', 'Drama', 137, 8.00),
(7, '2022-05-28', '09:00:00', 'Men', 'Horror', 25, 8.00),
(8, '2022-05-28', '09:00:00', 'The Bad Guys', 'Animation', 142, 8.00),
(9, '2022-05-28', '05:00:00', 'Top Gun Maverick', 'Action', 150, 13.00),
(10, '2022-05-28', '05:00:00', 'Downton Abbey A New Era', 'Drama', 118, 13.00),
(11, '2022-05-28', '05:00:00', 'Men', 'Horror', 88, 13.00),
(12, '2022-05-28', '05:00:00', 'The Bad Guys', 'Animation', 130, 13.00);
shell 复制代码
OutputQuery OK, 12 rows affected (0.00 sec)
Records: 12  Duplicates: 0  Warnings: 0

插入数据后,就可以开始在SQL中对查询结果进行排序了。

如何使用GROUP BY

GROUP BY语句的功能是将具有共享值的记录分组。在查询中,GROUP BY语句总是与聚合函数一起使用。您可能还记得,一个聚合函数总结信息,并返回一个结果。例如,你可以查询一列的总数或总和,这将在结果中产生一个值。使用GROUP BY子句,你可以实现聚合函数,为每个你想要的组获得一个结果值。

GROUP BY对于返回多个按指定组排序的期望结果很有用,而不是只按一列排序。此外,如果你选择使用FROM语句和WHERE子句,GROUP BY必须始终位于它们之后。下面是一个使用GROUP BY和聚合函数的查询结构的示例:

sql 复制代码
SELECT column_1, AGGREGATE_FUNCTION(column_2) FROM table GROUP BY column_1;

为了说明如何使用GROUP BY语句,假设你正在领导几部电影的发行活动,并且你想评估营销工作的成功。你让当地的一家剧院分享他们在周五和周六从客人那里收集的数据。首先通过运行SELECT*符号来查看数据,以选择movie_theater表中的所有列:

sql 复制代码
SELECT * FROM movie_theater;
shell 复制代码
Output+------------+------------+----------+-------------------------+-------------+-------------+-------------+
| theater_id | date       | time     | movie_name              | movie_genre | guest_total | ticket_cost |
+------------+------------+----------+-------------------------+-------------+-------------+-------------+
|          1 | 2022-05-27 | 10:00:00 | Top Gun Maverick        | Action      |         131 |       18.00 |
|          2 | 2022-05-27 | 10:00:00 | Downton Abbey A New Era | Drama       |          90 |       18.00 |
|          3 | 2022-05-27 | 10:00:00 | Men                     | Horror      |         100 |       18.00 |
|          4 | 2022-05-27 | 10:00:00 | The Bad Guys            | Animation   |          83 |       18.00 |
|          5 | 2022-05-28 | 09:00:00 | Top Gun Maverick        | Action      |         112 |        8.00 |
|          6 | 2022-05-28 | 09:00:00 | Downton Abbey A New Era | Drama       |         137 |        8.00 |
|          7 | 2022-05-28 | 09:00:00 | Men                     | Horror      |          25 |        8.00 |
|          8 | 2022-05-28 | 09:00:00 | The Bad Guys            | Animation   |         142 |        8.00 |
|          9 | 2022-05-28 | 05:00:00 | Top Gun Maverick        | Action      |         150 |       13.00 |
|         10 | 2022-05-28 | 05:00:00 | Downton Abbey A New Era | Drama       |         118 |       13.00 |
|         11 | 2022-05-28 | 05:00:00 | Men                     | Horror      |          88 |       13.00 |
|         12 | 2022-05-28 | 05:00:00 | The Bad Guys            | Animation   |         130 |       13.00 |
+------------+------------+----------+-------------------------+-------------+-------------+-------------+
12 rows in set (0.00 sec)

虽然这些数据很有用,但您希望对某些特定列进行更深入的评估并排序结果。

因为你工作在几个不同类型的电影,你有兴趣知道他们被电影观众好评。具体来说,你想知道观看每种类型电影的平均人数。使用SELECTmovie_genre列中检索各种类型的电影。然后对guest_total列应用聚合函数AVG,使用ASaverage列创建一个别名,并包含GROUP BY语句以movie_genre对结果进行分组。按这种方式分组可以得到每种电影类型的平均结果:

sql 复制代码
SELECT movie_genre, AVG(guest_total) AS average
FROM movie_theater 
GROUP BY movie_genre;
shell 复制代码
Output+-------------+----------+
| movie_genre | average  |
+-------------+----------+
| Action      | 131.0000 |
| Drama       | 115.0000 |
| Horror      |  71.0000 |
| Animation   | 118.3333 |
+-------------+----------+
4 rows in set (0.00 sec)

这个输出提供了movie_genre组中每种电影类型的四个平均值。根据这些信息,Action的平均每场观众人数最多。

接下来,假设你想要测量影院在两天内的收入。下面的查询从date列返回值,以及由SUM聚合函数返回的值。具体来说,聚合函数SUM将一个数学方程放在括号中,使用*操作符将总客人数量乘以一张票的成本,表示为:SUM(guest_total * ticket_cost)。该查询包含AS子句,为聚合函数返回的列提供别名total_revenue。然后使用GROUP BY语句完成查询,根据date列对查询结果进行分组:

sql 复制代码
SELECT date, SUM(guest_total * ticket_cost) 
AS total_revenue 
FROM movie_theater 
GROUP BY date;
shell 复制代码
Output+------------+---------------+
| date       | total_revenue |
+------------+---------------+
| 2022-05-27 |       7272.00 |
| 2022-05-28 |       9646.00 |
+------------+---------------+
2 rows in set (0.00 sec)

因为你使用了GROUP BYdate列进行分组,所以输出的结果是每天的总票房收入,在本例中是5月27日星期五7,272元,5月28日星期六9,646元。

现在假设你想关注并分析一部电影:《坏家伙》。在这种情况下,你想弄清楚时间和价格点如何影响一个家庭观看动画电影的选择。对于这个查询,使用聚合函数MAX来获取最大的ticket_cost,确保包含AS来为price_data列创建别名。然后,使用WHERE子句将结果通过movie_name缩小到只有"the Bad Guys",并使用and使用比较操作符 >来根据guest_total数字大于100来确定最受欢迎的电影次数。然后用GROUP BY语句完成查询,并按time分组:

sql 复制代码
SELECT time, MAX(ticket_cost) AS price_data 
FROM movie_theater
WHERE movie_name = "The Bad Guys" 
AND guest_total > 100
GROUP BY time;
shell 复制代码
Output+----------+------------+
| time     | price_data |
+----------+------------+
| 09:00:00 |       8.00 |
| 05:00:00 |      13.00 |
+----------+------------+
2 rows in set (0.00 sec)

根据这个输出,更多的客人在上午9点的早场时间去看《The Bad Guys》,这是一个更实惠的价格点,每张票8美元。然而,这些结果也显示,看电影的客人在下午5点时支付了更高的票价,为13美元,这表明家庭更喜欢在当天不会太晚的时间看电影,并且会为电影票支付更多的钱。与晚上10点的《The Bad Guys》相比,这似乎是一个公平的评价,当时只有83名观众,每张票的价格是18美元。这可以为电影院经理提供有用的信息,证明开放更多的日场和傍晚场次可以增加家庭的上座率,这些家庭正在根据首选的时间和价格点进行选择。

请注意,尽管GROUP BY几乎总是与聚合函数一起使用,但也可能有例外,尽管不太可能。然而,如果你想在没有聚合函数的情况下对结果进行分组,你可以使用DISTINCT语句来获得相同的结果。DISTINCT子句通过返回列中的唯一值来删除结果集中的重复项,并且它只能与SELECT语句一起使用。例如,如果你想将所有电影按名字分组,可以使用以下查询:

sql 复制代码
SELECT DISTINCT movie_name FROM movie_theater;
shell 复制代码
Output+-------------------------+
| movie_name              |
+-------------------------+
| Top Gun Maverick        |
| Downton Abbey A New Era |
| Men                     |
| The Bad Guys            |
+-------------------------+
4 rows in set (0.00 sec)

在查看表中的所有数据时,你会发现电影名称有重复,因为有多个放映场次。因此,DISTINCT删除了这些重复项,并有效地将唯一的值分组在单列movie_name下。这实际上与下面的查询相同,其中包含一个GROUP BY语句:

sql 复制代码
SELECT movie_name FROM movie_theater GROUP BY movie_name;

现在你已经练习了在聚合函数中使用GROUP BY,接下来你将学习如何使用ORDER BY语句对查询结果进行排序。

如何使用ORDER BY

ORDER BY语句的功能是根据你在查询中指定的列对结果进行升序或降序排序。根据后面指定的列存储的数据类型,ORDER by 将按字母或数字顺序组织它们。默认情况下,ORDER By 将按升序对结果进行排序;但是,如果你喜欢降序排列,你必须在查询中包含关键字DESC。你也可以将ORDER BY语句和GROUP BY一起使用,但它必须放在后面才能正常工作。与GROUP BY类似,ORDER BY也必须位于FROM语句和WHERE子句之后。ORDER BY的通用语法如下:

sql 复制代码
SELECT column_1, column_2 FROM table ORDER BY column_1;

让我们继续使用电影院的示例数据,并练习使用ORDER BY对结果进行排序。从下面的查询开始,它从guest_total列中检索值,并用ORDER BY语句组织这些数值:

sql 复制代码
SELECT guest_total FROM movie_theater 
ORDER BY guest_total;
shell 复制代码
Output+-------------+
| guest_total |
+-------------+
|          25 |
|          83 |
|          88 |
|          90 |
|         100 |
|         112 |
|         118 |
|         130 |
|         131 |
|         137 |
|         142 |
|         150 |
+-------------+
12 rows in set (0.00 sec)

因为你的查询指定了一个数值列,所以ORDER BY语句按照数值和升序排列结果,从guest_total列的25开始。

如果你想按降序对列进行排序,可以在查询语句的末尾添加DESC关键字。此外,如果你想根据movie_name下的字符值对数据进行排序,可以在查询中指定。让我们使用ORDER BY来执行这种类型的查询,以将movie_name列的字符值降序排列。通过包含一个WHERE子句来从time列中检索在10:00 pm放映的电影数据,从而进一步排序结果:

sql 复制代码
SELECT movie_name FROM movie_theater
WHERE time = '10:00:00' 
ORDER BY movie_name DESC;
shell 复制代码
Output+-------------------------+
| movie_name              |
+-------------------------+
| Top Gun Maverick        |
| The Bad Guys            |
| Men                     |
| Downton Abbey A New Era |
+-------------------------+
4 rows in set (0.01 sec)

这个结果集列出了晚上10点放映的四部不同的电影,按字母顺序降序排列,从《Top Gun Maverick》到《Downtown Abbey A New Era》。

对于下一个查询,将ORDER BYGROUP BY语句与聚合函数SUM结合起来,生成每部电影的总收益。但是,假设电影院错算了总人数,并且忘了包括那些预先购买并预定了每场12人的电影票的特殊派对。

在这个查询中使用SUM,通过实现运算符+,然后将12加到guest_total中,来包含每次电影放映的额外12位客人。一定要附上这个括号。然后,用运算符"*"乘以ticket_cost,并通过最后的圆括号完成数学方程。添加AS子句为名为total_revenue的新列创建别名。然后,使用GROUP BY来根据从movie_name列检索到的数据对每部电影的total_revenue结果进行分组。最后,使用ORDER BY将新列total_revenue下的结果以升序排列:

sql 复制代码
SELECT movie_name, SUM((guest_total + 12) * ticket_cost) 
AS total_revenue
FROM movie_theater 
GROUP BY movie_name 
ORDER BY total_revenue;
shell 复制代码
Output+-------------------------+---------------+
| movie_name              | total_revenue |
+-------------------------+---------------+
| Men                     |       3612.00 |
| Downton Abbey A New Era |       4718.00 |
| The Bad Guys            |       4788.00 |
| Top Gun Maverick        |       5672.00 |
+-------------------------+---------------+
4 rows in set (0.00 sec)

这个结果集告诉我们每部电影加上额外的12位观众的总票房收入,并将总票房收入从低到高排序。由此我们得知,《Top Gun Maverick》的票房收入最高,而《Men》的票房收入最低。与此同时,《The Bad Guys》和《Downton Abbey A New Era》在总票房上非常接近。

在本节中,你实践了多种实现ORDER BY语句的方法,以及如何指定你喜欢的顺序,例如字符型和数值型数据的升序和降序。你还学习了如何包含WHERE子句以缩小结果范围,并使用聚合函数和数学方程使用GROUP BYORDER BY语句执行查询。

总结

理解如何使用GROUP BYORDER BY语句对于对结果和数据进行排序是很重要的。你是想在一个组下组织多个结果,还是按字母和降序组织其中一列,还是同时进行这两种操作。你还了解了使用WHERE子句进一步排序结果的其他方法。

相关推荐
就这个java爽!5 分钟前
超详细的XML介绍【附带dom4j操作XML】
xml·java·开发语言·数据库·青少年编程·eclipse
_.Switch10 分钟前
Python Web 架构设计与性能优化
开发语言·前端·数据库·后端·python·架构·log4j
Shall#14 分钟前
Innodb存储架构
数据库·mysql·架构
SelectDB技术团队38 分钟前
Apache Doris 2.1.6 版本正式发布
大数据·数据库·数据仓库·开源·doris
不会八股文44 分钟前
达梦数据库导入xml迁移到达梦数据库大文件导致中断问题解决方案记录?
xml·数据库
拜见老天師1 小时前
SpringBoot中对数据库连接配置信息进行加密处理
数据库·spring boot·后端
萌新小码农‍1 小时前
汽车美容服务管理系统的数据库设计与数据操作
数据库·汽车
x66ccff1 小时前
【linux】快速列出 systemctl 特定名的服务
linux·服务器·数据库
Jiangw5571 小时前
【实战篇】MySQL是怎么保证主备一致的?
数据库·sql·mysql
胡小禾2 小时前
mongoDB-1
数据库·mongodb