MySQL数据库——子查询

 

 

#进阶7:子查询
/*
含义:出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询

分类:
    按子查询出现的位置
        select后面
            仅仅支持标量子查询
        from后面
            支持表子查询
        where、having后面 ※
            支持标量子查询(单行) ※,也支持列子查询(多行) ※,行子查询较少
        exists后面(相关子查询)
            支持表子查询
    按结果集行列数不同
        标量子查询(结果集只有一行一列)
        列子查询(结果集只有一列多行),也叫多行子查询
        行子查询(结果集有一行多列)
        表子查询(结果集随便几行几列)
        
*/
#一、where/having后面的子查询
/*
特点:
    都放在小括号内
    一般放在条件的右侧
    标量子查询:一般搭配单行操作符使用< > <= >= = 
    列子查询:一般搭配多行操作符使用in any or some
    子查询的执行优先于主查询的执行,因为主查询用到了子查询的结果

*/
#1.标量子查询(单行子查询)
#案例:谁的工资比Abel高
#①查询名字叫Abel的工资
SELECT salary
FROM employees
WHERE last_name = 'Abel';
#②查询员工的信息满足条件
SELECT *
FROM employees
WHERE salary > (
    SELECT salary
    FROM employees
    WHERE last_name = 'Abel'
);
#案例:返回job_id与141号员工相同,salary比143号员工多的员工姓名、job_id和工资
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_bame,job_id,salary
SELECT last_name,job_id,salary
FROM employees
WHERE salary = (
    SELECT MIN(salary)
    FROM employees
);
#案例:查询最低工资大于50号部门的最低工资的部门id和最低工资
#查询每个部门的最低工资,筛选最低公司大于50号部门的
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary) >  (
    SELECT MIN(salary)
    FROM employees
    WHERE department_id = 50
);
#非法使用标量子查询
#一行一列!
#子查询必要要能查出来!

#2.列子查询(多行子查询,一列多行)
#案例:返回location_id是1400或1700的部门中的所有员工姓名
#①查询location_id是1400或1700的部门编号
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN(1400,1700);
#②查询这些部门的所有员工姓名
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 last_name,employee_id,salary
FROM employees
WHERE salary < ANY(
    SELECT DISTINCT salary
    FROM employees
    WHERE job_id = 'IT_PROG'
)AND job_id <> 'IT_PROG';
#案例:返回其他工种中比job_id为'IT_PROG‘部门所有工资低的员工的工号、姓名、job_id以及salary
SELECT last_name,employee_id,salary
FROM employees
WHERE salary < ALL(
    SELECT DISTINCT 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后面
#案例:查询每个部门的员工个数
SELECT d.*,(
    SELECT COUNT(*) 
    FROM employees e
    WHERE e.department_id = d.`department_id`
)
FROM departments d;

#三、放在from后面
#将查询的结果集充当数据源,必须其别名
#案例:查询每个部门的平均工资的工资等级
SELECT ag_dep.*,g.`grade_level`
FROM (
    SELECT AVG(salary) ag,department_id
    FROM employees
    GROUP BY department_id
) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

#四、exists后面(相关子查询)
#判断子查询的结果有没有值
SELECT EXISTS(SELECT employee_id FROM employees);#1
#案例1:查询有员工的部门名
SELECT department_name
FROM departments d
WHERE EXISTS(
    SELECT *
    FROM employees e
    WHERE e.`department_id` = d.`department_id`
);

 

posted @ 2021-02-19 14:13  不妨不妨,来日方长  阅读(307)  评论(0编辑  收藏  举报