本篇主要内容
六种聚集函数的使用,ORDER BY
数据分组,子查询( 相关子查询 与 不相关子查询 )。内容稍稍有些多,需要静下心来慢慢看,如果条件允许可以动手实践一下(数据库文件在系列首页)。话不多说,进入正题!
先来看一下,我们常用的聚集函数和它的说明。
函数 | 说明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行数 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
查询供应商 id
为 'DLL01'
的所有商品的平均价格。
mysql> SELECT AVG(prod_price) AS avg_price
-> FROM Products
-> WHERE vend_id = 'DLL01';
+-----------+
| avg_price |
+-----------+
| 3.865000 |
+-----------+
两种使用方式:
COUNT(*)
对表中行的数目进行计数,包括 空值 。查询 Customers
表中的顾客数量。
mysql> SELECT COUNT(*) AS num_cust
-> FROM Customers;
+----------+
| num_cust |
+----------+
| 5 |
+----------+
COUNT(column)
对特定列中非 NULL
行进行计数。查询 Customers
表中非空邮箱数。
mysql> SELECT COUNT(cust_email) AS num_cust
-> FROM Customers;
+----------+
| num_cust |
+----------+
| 3 |
+----------+
当 column
列为数值列, MAX(column)
返回 column
列中的最大值。
当 column
列为文本数据, MAX(column)
返回 column
列数据 排序 后的最后一行。
当 column
列为数值列, MIN(column)
返回 column
列中的最小值。
当 column
列为文本数据, MIN(column)
返回 column
列数据 排序 后的最前面的行。
SUM()
用来返回指定列值的和(总计)(忽略列值为 NULL
的行)。
查询 OrderItems
表中的商品总价之和。先计算出(数量 * 物品单价),再对其求和。
mysql> SELECT SUM(quantity * item_price) AS total_price
-> FROM OrderItems;
+-------------+
| total_price |
+-------------+
| 5730.70 |
+-------------+
计算 Products
表中物品的数目,产品价格的最高值、最低值以及平均值。
mysql> SELECT COUNT(*) AS num_items,
-> MIN(prod_price) AS price_min,
-> MAX(prod_price) AS price_max,
-> AVG(prod_price) AS price_avg
-> FROM Products;
+-----------+-----------+-----------+-----------+
| num_items | price_min | price_max | price_avg |
+-----------+-----------+-----------+-----------+
| 9 | 3.49 | 11.99 | 6.823333 |
+-----------+-----------+-----------+-----------+
使用分组将数据分为多个逻辑组, 对每个组进行聚集计算。使用聚集函数才能够
统计各个供应商的产品数量。
mysql> SELECT vend_id, COUNT(*) AS num_prods
-> FROM Products
-> GROUP BY vend_id;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| BRS01 | 3 |
| DLL01 | 4 |
| FNG01 | 2 |
+---------+-----------+
group by
注意事项:
GROUP BY
可以嵌套使用。GROUP BY
子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在 SELECT
中使用表达式,则必须在 GROUP BY
子句中指定相同的表达式。不能使用别名。SELECT
语句中的每一列都必须在 GROUP BY
子句 中给出。NULL
值的行,则 NULL
将作为一个分组返回。 如果列中有多行 NULL
值,它们将分为一组。GROUP BY
子句必须出现在 WHERE
子句之后,ORDER BY
子句之前。使用 HAVING
子句在数据分组后进行过滤。
例:查询 Products
表中有两个以上产品且其价格大于等于 4 的供应商。
mysql> SELECT vend_id, COUNT(*) AS num_prods
-> FROM Products
-> WHERE prod_price >= 4
-> GROUP BY vend_id
-> HAVING COUNT(*) >= 2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| BRS01 | 3 |
| FNG01 | 2 |
+---------+-----------+
WHERE
与 HAVING
的主要区别:
WHERE
是一个约束声明,HAVING
是一个过滤声明。WHERE
在数据分组前进行过滤,HAVING
在数据分组后进行过滤。SELECT
子句顺序:
子句 | 说明 | 是否必须使用 |
---|---|---|
SELECT | 要返回的列或表达式 | 是 |
FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
WHERE | 行级过滤 | 否 |
GROUP BY | 分组说明 | 仅在按组计算聚集时使用 |
HAVING | 组级过滤 | 否 |
ORDER BY | 输出排序顺序 | 否 |
按照相关性来分:分为 相关子查询 和 不相关子查询 。
where
子句返回真值,说明符合;否则不符合,则舍弃。按照子查询所在位置分:WHERE
或 HAVING
后、SELECT
后、FROM
后、EXISTS
后的子查询。
下面按照位置划分来进行介绍,期间会标注示例是否为相关子查询。
在订单表中查找最早日期的订单信息。子查询返回一行查询结果。(该示例为不相关子查询)
mysql> SELECT *
-> FROM Orders
-> WHERE order_date = (SELECT MIN(order_date)
-> FROM Orders);
+-----------+---------------------+------------+
| order_num | order_date | cust_id |
+-----------+---------------------+------------+
| 20006 | 2012-01-12 00:00:00 | 1000000003 |
+-----------+---------------------+------------+
查询订购物品 RGAN01
的所有顾客。这时子查询先从 OrderItems
表中找出包含 RGAN01
物品的订单号,再根据这些订单号在 Orders
表中找到对应的顾客 id
。(该示例为不相关子查询)
mysql> SELECT cust_id
-> FROM Orders
-> WHERE order_num IN (SELECT order_num
-> FROM OrderItems
-> WHERE prod_id = 'RGAN01');
+------------+
| cust_id |
+------------+
| 1000000004 |
| 1000000005 |
+------------+
操作符 | 含义 |
---|---|
IN / NOT IN | 在列表中 / 不在列表中 |
ANY / SOME | 和子查询返回的某一个值比较 |
ALL | 同子查询结果中所有值进行比较 |
用法对比:ANY / SOME
:
SELECT ... FROM ... WHERE num > ANY(num1, num2)
SELECT ... FROM ... WHERE num > num1 OR num > num2
ALL
:
SELECT ... FROM ... WHERE num > ALL(num1, num2)
SELECT ... FROM ... WHERE num > num1 AND num > num2
注意:
SELECT
语句中,子查询总是从内向外处理。假如需要显示 Customers
表中每个顾客的订单总数。首先,从 Customers
表中检索顾客列表,然后对于检索出的每个顾客,统计其在 Orders
表中的订单数目。(该示例为相关子查询)
mysql> SELECT cust_name,
-> (SELECT COUNT(*)
-> FROM Orders AS ord
-> WHERE ord.cust_id = cust.cust_id) AS order_count
-> FROM Customers AS cust;
+---------------+-------------+
| cust_name | order_count |
+---------------+-------------+
| Village Toys | 2 |
| Kids Place | 0 |
| Fun4All | 1 |
| Fun4All | 1 |
| The Toy Store | 1 |
+---------------+-------------+
注意:上面的例子中使用的是 Ord.cust_id
和 cust.cust_id
,而不是直接使用 cust_id
,因为在两个表中都有 cust_id
列,在有可能混淆列名时必须使用这种语法。
将子查询结果作为一张表,并必须要起别名。
下面的例子可能有点复杂,它还涉及到之后我们将学习的表联结,这里使用的联结方式是内联结,根据设定的条件进行等值联结。
查询目标为美国供应商名称和它的产品名称,我们一步步分析,首先先通过子查询获取供应商 Vendors
表中国家为 USA
的供应商信息,再将子查询的结果作为 USA_Vendors
表,将 Products
表与该表联结,联结条件为两表 vend_id
列相等。(该示例为不相关子查询)
mysql> SELECT vend_name, prod_name
-> FROM Products, (SELECT *
-> FROM Vendors
-> WHERE vend_country = 'USA') AS USA_Vendors
-> WHERE Products.vend_id = USA_Vendors.vend_id;
+-----------------+---------------------+
| vend_name | prod_name |
+-----------------+---------------------+
| Bears R Us | 8 inch teddy bear |
| Bears R Us | 12 inch teddy bear |
| Bears R Us | 18 inch teddy bear |
| Doll House Inc. | Fish bean bag toy |
| Doll House Inc. | Bird bean bag toy |
| Doll House Inc. | Rabbit bean bag toy |
| Doll House Inc. | Raggedy Ann |
+-----------------+---------------------+
现在使用 EXISTS
来实现上面 IN
实现的查询。即查询订购物品 RGAN01
的所有顾客。
mysql> SELECT cust_id
-> FROM Orders AS ord
-> WHERE EXISTS (SELECT *
-> FROM OrderItems AS ori
-> WHERE ord.order_num = ori.order_num
-> AND prod_id = 'RGAN01');
+------------+
| cust_id |
+------------+
| 1000000004 |
| 1000000005 |
+------------+
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_43965708/article/details/117409317
内容来源于网络,如有侵权,请联系作者删除!