标签(空格分隔): MySQL
进阶七 子查询
含义:出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类: 子查询出现的位置:
select后面:
仅仅支持标量子查询
from后面:
支持表子
where或having后面(▼)
标量子查询:单行(▼)
列子查询:多行(▼)
sxists后面(相关子查询)
表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果只有一列多行)
表子查询(结果集一般为多行多列)
where或having后面
1、标量子查询(单行子查询)
2、列子查询(多子行查询)
3、行子查询
特点:
- 子查询放在小括号里
- 子查询放在条件的右侧
- 标量子查询,一般搭配着单行操作符使用
< >= <= = <>
列子查询,一般搭配多行操作符使用
4. 子查询的执行优于主查询执行,主查询的条件用到了子查询的结果
一、标量子查询
案例1、查询谁的工资比Abel高?
1.查询Abel的工资
SELECT `salary`
FROM `employees`
WHERE `last_name`='Abel' ;
2.查询员工信息,满足工资比Abel高
SELECT *
FROM `employees`
WHERE `salary` > (
SELECT `salary`
FROM `employees`
WHERE `last_name`='Abel'
) ;
案例2、返回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与2,求所求
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'
) ;
案例三、返回公司工资最少的员工的last_name,job_id和salary
1.返回公司工资最少的工资
SELECT MIN(`salary`)
FROM `employees` ;
2.返回公司工资最少的员工的last_name,job_id和salary
SELECT `last_name`,`job_id`,`salary`
FROM `employees`
WHERE `salary` = (
SELECT MIN(`salary`)
FROM `employees`
) ;
案例四、查询最低工资大于50号部门最低工资的部门id和其最低工资
1.查询50号部门的最低工资
SELECT MIN(`salary`)
FROM `employees`
WHERE `department_id` = 50 ;
2.查询每个部门的最低工资
SELECT MIN(`salary`)
FROM `employees`
GROUP BY `department_id` ;
3.筛选2,满足min(salary)> 1.
SELECT `employee_id`,MIN(`salary`)
FROM `employees`
GROUP BY `department_id`
HAVING MIN(`salary`) > (
SELECT MIN(`salary`)
FROM `employees`
WHERE `department_id` = 50
) ;
非法使用子查询的情况
- 子查询只能是标量子查询
二、列子查询(多行子查询)
多行操作符:
操作符 | 含义 |
---|---|
IN/NOT IN | 等于列表中的任意一个 |
ANY/SOME | 和子查询返回的某一个值比较 |
ALL | 和子查询返回的所有值比较 |
案例1:返回location——id是1400或1700的部门中所有员工姓名
-
查询location——id是1400或1700的部门编号
SELECT DISTINCT department_id
FROMdepartments
WHERElocation_id
IN (1400,1700); -
查询员工姓名,要求部门号是1.中的某一个
SELECT
last_name
FROMemployees
WHEREdepartment_id
IN( SELECT
DISTINCT department_id FROMdepartments
WHERElocation_id
IN
(1400,1700) ) ;
案例2:返回其他工种中比job_id为IT_PROG部门任一工资低的员工的员工号,姓名,job_id以及salary
1.查询job_id为IT_PROG部门任一工资
SELECT DISTINCT`salary`
FROM `employees`
WHERE `job_id` = 'it_prog' ;
2.查询员工号,姓名,job_id以及salary,要求salary < 1.中的任意一个
SELECT `employee_id`,`last_name`,`job_id`,`salary`
FROM `employees`
WHERE `salary` < ANY(
SELECT DISTINCT`salary`
FROM `employees`
WHERE `job_id` = 'it_prog'
)
AND `job_id` <> 'IT_PROG' ;
案例3:返回其他工种中比job_id为IT_PROG部门所有工资低的员工的员工号,姓名,job_id以及salary
三、行子查询
案例:查询员工编号最小并且工资最高的员工信息
行子查询写法:
SELECT *
FROM `employees`
WHERE (`employee_id`,`salary`) =(
SELECT MIN(`employee_id`),MAX(`salary`)
FROM `employees`
) ;
一般写法:
SELECT *
FROM `employees`
WHERE `employee_id` =(
SELECT MIN(`employee_id`)
FROM `employees`
)
AND(
SELECT MAX(`salary`)
FROM `employees`
) ;
行子查询写法
select的后面
仅仅支持标量子查询
案例1:查询每个部门的员工个数
SELECT d.*,(
SELECT COUNT(*)
FROM `employees` AS e
WHERE e.`department_id` = d.`department_id`
) AS 个数
FROM `departments` AS d ;
案例2:查询员工号=102的部门名
SELECT (
SELECT `department_name`
FROM `departments` AS d
INNER JOIN `employees` AS e
ON d.`department_id` = e.`department_id`
WHERE e.`employee_id` = 102
) ;
from后面
将子查询结果充当一张表,要求必须起别名
案例:查询每个部门的平均工资的工资等级
1.查询每个部门的平均工资
SELECT AVG(`salary`),`department_id`
FROM `employees`
GROUP BY `department_id` ;
2.连接1.的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal
SELECT ag_dep.*,g.`grade_level`
FROM (
SELECT AVG(`salary`) AS ag,`department_id`
FROM `employees`
GROUP BY `department_id`
) AS ag_dep
INNER JOIN `job_grades` AS g
ON ag_dep.ag BETWEEN `lowest_sal` AND `highest_sal`
GROUP BY ag_dep.ag ;
exists后面(相关子查询)
语法:
exists(完整的查询语句)
结果:1或0
案例一:查询有员工的部门名
SELECT `department_name`
FROM `departments` AS d
WHERE EXISTS(
SELECT *
FROM `employees` AS 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`
) ;
案例二:查询没有女盆友的男神信息
in写法
SELECT bo.*
FROM`boys` AS bo
WHERE bo.id NOT IN(
SELECT `boyfriend_id`
FROM `beauty`
) ;
SELECT *
FROM `beauty`;
SELECT bo.*
FROM beys AS bo
WHERE NOT EXISTS(
SELECT `boyfriend_id`
FROM `beauty` AS b
WHERE b.`boyfriend_id` = bo.id
) ;
进阶八:分页查询
应用场景:当要显示的数据,一页显示不全,需要分页提交SQL请求
语法:
select 查询列表
from 表
【join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排列的字段】
limit 【offset,】size;
offset:要显示的条目的起始索引(起始索引从0开始)
思泽:要显示的条目个数
特点:
- limit语句放在查询语句最后
- 公式:
要显示的页数page,每页的条目数size
limit (page-1)*size,size
案例一:查询前五条员工信息
SELECT *
FROM `employees`
LIMIT 0,5 ;
或
SELECT *
FROM `employees`
LIMIT 5 ;
案例二:查询第11条到第25条员工信息
SELECT *
FROM `employees`
LIMIT 10,15 ;
案例三:有奖金的员工信息,并且工资较高的前十名显示出来
SELECT *
FROM `employees`
WHERE `commission_pct` IS NOT NULL
ORDER BY `salary` ASC
LIMIT 10 ;
进阶九:联合查询
union 联合 合并:将多条查询语句的结果合并成一个结果
语法:
查询语句1
union
查询语句2
...
应用场景: 要查询的结果来自多个表,且多个表没有直接的链接关系,单查询的信息一致时
特点:
1.要求多条查询语句的查询列数是一致的!
2.要求多条查询语句的查询的每一列的类型和顺序最好相同,以第一个查询语句为表头
3.union关键字默认去重,如果使用union all可以包括重复项
引入案例:查询部门编号>90或邮箱包含a的员工信息
一般方法:
SELECT *
FROM `employees`
WHERE `email` LIKE '%a%'
OR `department_id`>90 ;
联合查询:
SELECT *
FROM `employees`
WHERE `email`
LIKE '%a%'
UNION
SELECT *
FROM `employees`
WHERE `department_id` > 90 ;
案例:查询中国用户中男性的信息以及外国用户中男性的用户信息
SELECT id,coame,csex FROM t_ca WHERE csex = '男'
UNION
SELECT t_id,tName,tGender FROM t_ua WHERE tGender = 'malie'
标签:salary,employees,基础,查询,学习,MySQL,WHERE,id,SELECT
From: https://www.cnblogs.com/fengmian13wl/p/18348593