05-MySQL子查询

本文详细介绍了SQL中的子查询,包括子查询的分类、使用位置和特点。重点讲解了WHERE或HAVING后面的标量子查询、列子查询和行子查询,给出了多个示例,如找工资高于特定员工的员工、比较不同部门工资等。同时,文章还讨论了子查询中的空值问题和多行操作符的使用,以及如何避免常见的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


概念:出现在其他语句内部的select语句,称为子查询或内查询

内部嵌套其他select语句的查询,称为外查询或主查询

示例:

select first_name 
from employees 
where department_id in(
	select department_id 
    from departments
	where location_id=1700
)

1. 子查询分类

(1)按子查询出现的位置:

  • SELECT后面:仅仅支持标量子查询
  • FROM后面:支持表子查询
  • WHERE或HAVING后面:(☆)
    • 标量子查询(单行)(☆)
    • 列子查询(一列多行)(☆)
    • 行子查询(一行多列)
  • EXISTS后面:表子查询

(2)按结果集的行列数不同:

  • 标量子查询(结果集只有一行一列)
  • 列子查询(结果集只有一列多行)
  • 行子查询(结果集有一行多列)
  • 表子查询(结果集一般为多行多列)

(3)特点:

  • 子查询(内查询) 在主查询之前一次执行完成。
  • 子查询的结果被主查询(外查询)使用

2. WHERE或HAVING后面

  • 标量子查询(单行子查询)(☆)
  • 列子查询(多行子查询)(☆)
  • 行子查询(多列子查询)

特点:

(1)子查询要包含在括号内。

(2)将子查询放在比较条件的右侧。

(3)单行操作符对应标量子查询(单行子查询),一般搭配单行操作符使用 > < >= <= = <>

(4)多行操作符对应列子查询(多行子查询),一般搭配多行操作符使用,例如 IN、ANY/SOME、ALL

2.1 标量子查询

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

首先,子查询来查询Abel的工资(1),然后在员工信息中查询满足salary>(1)的结果。

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

题目:返回 job_id与141号员工相同,salary比143号员工多的员工姓名,job_id 和工资

(1)查询141号员工的job_id
SELECT job_id
FROM employees
WHERE employee_id = 141

(2)查询143员工的salary
SELECT salary
FROM employees
WHERE employee_id = 143

(3)合并(1)(2SELECT 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
)

在子查询中使用组函数

题目:返回公司工资最少的员工的 last_name, job_id 和 salary

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

子查询中的HAVING 子句

首先执行子查询。向主查询中的HAVING 子句返回结果。

题目:查询最低工资大于50号部门最低工资的部门id和其最低工资

(1)查询50号部门最低工资
SELECT MIN(salary)
FROM employees
WHERE department_id = 50;

(2)查询每个部门的最低工资
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id;

(3)(2)基础上选择MIN(salary)>(1)SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary) > (
    SELECT MIN(salary)
	FROM employees
	WHERE department_id = 50;
)

非法使用标量子查询(单行操作符>里面只能搭配标量子查询)

SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary) > (
    SELECT salary
	FROM employees
	WHERE department_id = 50;  #里面查询结果是50部门的工资列表,不是单列单行,不能搭配单行操作符>
)

子查询中的空值问题

SELECT last_name, job_id
FROM employees
WHERE job_id =(
    SELECT job_id
    FROM employees
    WHERE last_name = 'Haas' #没有符合该条件的值,里面是空值,也会报错
);

2.2 列子查询

返回多行。

使用多行比较操作符。

在这里插入图片描述
any和all一般可以用最大最小值替换,用的较少

题目:返回 location_id是1400或1700的部门中的所有员工姓名

(1)查询 location_id是14001700的部门编号
SELECT department_id
FROM departments
WHERE location_id IN(1400,1700)
#上面查询出来的结果是一列多行

(2)查询员工姓名,要求部门号是(1)列表中的某一个
SELECT last_name
FROM employees
WHERE department_id IN(
    SELECT DISTINCT department_id
	FROM departments
	WHERE location_id IN(1400,1700)
)

题目:返回其它部门中比 job_id 为 ‘IT_PROG’ 部门任一工资低的员工的员工号、姓名、job_id 以及salary

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';

或者改为MAX(),实现效果也是一样的

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

题目:返回其它部门中比 job_id 为 ‘IT_PROG’ 部门所有工资都低的员工的员工号、姓名、job_id 以及salary

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

或者改成MIN()

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

2.3 行子查询(用得少)

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

以往查询方法

(1)查询最小的员工编号
SELECT MIN(employee_id)
FROM employees

(2)查询最高工资
SELECT MAX(salary)
FROM employees

(3)查询员工信息
SELECT *
FROM employees
WHERE employee_id = (
    SELECT MIN(employee_id)
	FROM employees
)AND salary=(
    SELECT MAX(salary)
	FROM employees
)

行子查询方法

SELECT *
FROM employees
WHERE (employee_id,salary) = (
    SELECT MIN(employee_id),MAX(salary)
	FROM employees
)

select后面子查询(用得少)

from后面子查询(用得少,将子查询结果充当一张表,要求必须起别名)

3. exists后面的子查询

语法:

exists(完整的查询语句)

结果:1或0

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

SELECT department_name
FROM departments d
WHERE EXISTS(
    SELECT *
    FROM employees e
    WHERE d.'department_id' = e.'department_id'
)

可以用in实现

SELECT department_name
FROM departments d
WHERE d.'department_id' IN(
    SELECT department_id
    FROM employees
)

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

# exists
SELECT bo.*
FROM boys bo
WHERE NOT EXISTS(
    SELECT boyfriend_id
    FROM beauty b
    WHERE bo.'id'=b.'boyfriend_id'
)

#in
SELECT bo.*
FROM boys bo
WHERE bo.'id' NOT IN(
    SELECT b.'boyfriend_id'
    FROM beauty b
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值