【大数据系列之MySQL】(二十五):MySQL中的子查询

子查询:出现在其它语句内部的select语句,称为子查询或内查询,就是嵌套的查询结果集

子查询分类

按子查询出现的位置:

  • select后面:仅仅支持标量子查询
  • from后面:支持表子查询
  • where或having后面:标量子查询、列子查询、行子查询
  • exists后面(相关子查询)

按结果集的行列数不同:

  • 标量子查询:结果集只有一行一列
  • 列子查询:结果集只有一列多行
  • 行子查询:结果集有一行多列,也可多行多列
  • 表子查询:结果集一般为多行多列

特点:

  • 子查询放在小括号内
  • 子查询一般放在条件的右侧
  • 标量子查询一般搭配单行操作符的使用(> < <= >= = <>)
  • 列子查询一般搭配多行操作符的使用(in、any、all)

一、where后面子查询

1.标量子查询

案例1:谁的工资比Abel高?

首先需要查询出Abel的工资,查询结果为一个标量集,所以在where后面当一个常量值使用

SELECT
	last_name,
	salary 
FROM
	employees 
WHERE
	salary > (
	SELECT
		salary 
	FROM
		employees 
WHERE
	last_name = 'Abel')

案例2:返回job_id与141号员工相同,salary比143号员工多的员工姓名、job_id和工资

首先需要查询出141号的job_id,然后再查询出143号的salary,然后再主查询中进行条件筛选

SELECT last_name, job_id, salary 
FROM employees 
WHERE job_id = ( 
    SELECT 
    	job_id 
    FROM 
    	employees 
    WHERE 
    	employee_id = 141) 
AND salary >(
	SELECT
		salary 
	FROM
		employees 
	WHERE
		employee_id = 143)

案例3:返回公司工资最少的员工的last_name,job_id和salary

SELECT
	last_name,
	job_id,
	salary 
FROM
	employees 
WHERE
	salary =(
	SELECT
		min( salary ) 
FROM
	employees)

案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资

SELECT
	department_id,
	min( salary ) 
FROM
	employees 
GROUP BY
	department_id 
HAVING
	min( salary ) > (
	SELECT
		MIN( salary ) 
	FROM
		employees 
WHERE
	department_id = 50)

2.列子查询

案例1:返回location_id是1400或1700的部门中的所有员工姓名

首先查询出location_id为1400或1700的部门编号

SELECT
	last_name 
FROM
	employees 
WHERE
	department_id IN (
	SELECT
		department_id 
	FROM
		departments 
	WHERE
	location_id IN ( 1400, 1700 ) 
	)

案例2:返回其他工种中比job_id为‘IT_PROG’工种任一工资低的员工的员工号、姓名、job_id以及salary

首先查询出工种为IT_PROG的工资列表,由于是小于任一,也就是小于其中任意一个就行,所以使用any关键字进行筛选

SELECT
	employee_id,
	last_name,
	job_id,
	salary 
FROM
	employees 
WHERE
	salary < ANY ( SELECT salary FROM employees WHERE job_id = 'IT_PROG' ) 
	AND job_id <> 'IT_PROG';

3.行子查询

案例:查询员工编号最小并且工资最高的员工信息

先把最小编号和最高工资查询出来,是一个行信息,然后用于之后的筛选

SELECT
	* 
FROM
	employees 
WHERE
	( employee_id, salary ) = ( SELECT min( employee_id ), max( salary ) FROM employees );

二、select后面子查询

案例1:查询每个部门的员工个数及其部门信息

SELECT
	d.*,
	( SELECT count(*) FROM employees WHERE department_id = d.department_id ) 
FROM
	departments d;

案例2:查询员工号为102的部门名

SELECT
	( SELECT department_name FROM departments d JOIN employees e ON d.department_id = e.department_id WHERE e.employee_id = 102 );

三、from后面子查询

案例:查询每个部门的平均工资的工资等级

首先查出每个部门的平均工资,相当于一张新的表,由于是中间数据新表,所以需要起别名,然后再使用sql99的非等值连接即可

SELECT
	avg,
	grade_level 
FROM
	( SELECT avg( salary ) avg FROM employees GROUP BY department_id ) a
	JOIN job_grades j ON a.avg BETWEEN j.lowest_sal 
	AND j.highest_sal;

四、exists后面(相关子查询)

exist可以看成一个函数,该函数判断给定结果集中是否有数据,如果有则返回1,否则返回0,就是一个判断结果集是否为空的函数

案例1:查询有员工的部门名

可以看成是双重for循环,首先遍历部门表,拿着部门id去筛选,判断员工表中是否有员工的部门id等于该id,一旦有返回的集合就不为空,该部门名选中,如果没有则返回空。

第二种方式使用in,首先查询出员工表中是否有部门表中的部门id,然后使用in判断部门表的部门id是否在该子查询中

# 方式一
SELECT
	department_name 
FROM
	departments d 
WHERE
	EXISTS (
	SELECT
		* 
	FROM
		employees 
	WHERE
	department_id = d.department_id 
	)
	
# 方式二
SELECT
	department_name 
FROM
	departments d 
WHERE
	department_id IN (
	SELECT
		department_id 
	FROM
		employees 
WHERE
	department_id = d.department_id)

案例2:查询没有女朋友的男神信息

方式一使用exist,拿着男表中的id去查询女表中,一旦查询出结果,那么则返回1,所以使用notexist,不存在即结果集为空则筛选对该男信息

方式二使用not in,查询出女表中的所有boyid,然后判断男表的id是否在其中

# 方式一
SELECT
	* 
FROM
	boys 
WHERE
	NOT EXISTS (
	SELECT
		* 
	FROM
		beauty 
	WHERE
	boyfriend_id = boys.id 
	)
	
# 方式二
SELECT
	* 
FROM
	boys 
WHERE
	id NOT IN ( SELECT boyfriend_id FROM beauty );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海洋 之心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值