SELECT使用子查询

目录

1、子查询

2、利用子查询进行过滤

3、作为计算字段使用子查询

4、小结


博主用的是mysql8 DBMS,附上示例资料:

百度网盘链接: https://pan.baidu.com/s/1XaWi3Y7hpXbs_uHq2cPI6Q

提取码: fpnx

1、子查询

SELECT 语句是 SQL 的查询。我们迄今为止所看到的所有 SELECT 语句都是简单查询,即从单个数据库表中检索数据的单条语句。

查询(query) :任何 SQL 语句都是查询。但此术语一般指 SELECT 语句。

SQL 还允许创建子查询subquery),即嵌套在其他查询中的查询。为什么要这样做呢?理解这个概念的最好方法是考察几个例子。

说明:MySQL 支持

如果使用 MySQL,应该知道对子查询的支持是从 4.1 版本引入的。MySQL 的早期版本不支持子查询。

2、利用子查询进行过滤

现在,假如需要列出订购物品 ANV01 的所有顾客的信息,应该怎样检索?下面列出具体的步骤。

  • 找到包含物品 ANV01 的订单号
  • 根据订单号找到顾客的ID
  • 根据顾客的ID查找顾客的信息
-- 先找到有订购 ANV01 的订单号
SELECT order_num
FROM orderitems
WHERE prod_id = 'ANV01';
-- 20005

-- 在找到该订单号的所有顾客id
SELECT cust_id
FROM orders
WHERE order_num IN (20005);
-- 10001

-- 最后根据顾客id返回顾客的信息
SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (10001);

这里使用子查询是如何呢?就是在过滤时以子查询的结果作为过滤的条件

-- 使用子查询
SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (SELECT cust_id
					FROM orders
					WHERE order_num IN (SELECT order_num
										FROM orderitems
										WHERE prod_id = 'ANV01');

为了执行上述 SELECT 语句,DBMS 实际上必须执行三条 SELECT 语句。最里边的子查询返回订单号列表,此列表用于其外面的子查询的 WHERE子句。外面的子查询返回顾客 ID 列表,此顾客 ID 列表用于最外层查询的 WHERE 子句。最外层查询返回所需的数据。

可见,在 WHERE 子句中使用子查询能够编写出功能很强且很灵活的 SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询

 注意:只能是单列:作为子查询的 SELECT 语句只能查询单个列。企图检索多个列将返回错误。

3、作为计算字段使用子查询

使用子查询的另一方法是创建计算字段。假如需要显示 Customers 表中每个顾客的订单总数。订单与相应的顾客 ID 存储在 Orders 表中。执行这个操作,要遵循下面的步骤:

  • Customers 表中检索顾客列表;
  • 对于检索出的每个顾客,统计其在 Orders 表中的订单数目。

这里有一个问题,就是要对所有顾客进行订单统计,也就是包括并没有订单的顾客。

  • 使用上面子查询用于过滤的效果:没有订单的顾客不会进行统计
SELECT COUNT(*) AS cust_oders
FROM orders
WHERE cust_id IN (SELECT cust_id
					FROM customers)
GROUP BY cust_id;
-- 上面会有一种问题,就是没有订单的顾客不会显示订单数,显然不符合需求
-- 我们需要对customers中的每一个cust_id进行统计,所以不能用IN
  • 作为计算字段使用子查询: 
-- 所以cust_id不应该以订单表为准,应该以顾客表为准,但是又需要与订单表中的id进行比较
-- 这里开始使用完全限定列名:即表名+列名,作为计算字段使用子查询:
SELECT cust_name, 
		cust_id, 
		(SELECT COUNT(*)
		FROM orders
		WHERE Orders.cust_id = Customers.cust_id) AS cust_orders
FROM customers
ORDER BY cust_name;
/*
	上面sql语句较为复杂:它首先从customers中拿到了整个表的数据
	然后逐行检索出cust_name,cust_id
	其中的计算字段是一个select子查询,因为已经拿到了所有Customers.cust_id
	所以可以逐行以其为过滤条件,去统计该id再orders中的行数,如果没有就为0行
*/

这条 SELECT 语句对 Customers 表中每个顾客返回三列:cust_name、cust_state 和 ordersorders 是一个计算字段,它是由圆括号中的子查询建立的。该子查询对检索出的每个顾客执行一次。(也就是说,过滤后的数据是一行一行进行计算的)

子查询中的 WHERE 子句与前面使用的 WHERE 子句稍有不同,因为它使用了完全限定列名,而不只是列名( cust_id)。它指定表名和列名(Orders.cust_id Customers.cust_id)。下面的 WHERE 子句告诉 SQL,比较Orders表中的cust_id和当前正从Customers表中检索的cust_id:WHERE Orders.cust_id = Customers.cust_id

4、小结

  • 子查询就是在SELECT语句中嵌套了SELECT语句,但是这种子查询只能查询单列,否则会报错 
  • 除了用于过滤外,子查询还可用于计算字段,过滤后的结果是一行一行进行计算的
  • 当两表或多表中有相同的属性列,需要使用完全限定名--即表名.列名,避免混淆 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值