mysql子查询

前言

假如我们想要知道哪些员工的额薪水大于所有员工的平均薪水值

表结构如下:

CREATE TABLE employee  (
    id int NOT NULL,
    first_name varchar(50) NULL DEFAULT NULL COMMENT '名字',
    last_name varchar(50) NULL DEFAULT NULL COMMENT '姓',
    salary decimal(10, 2) NULL DEFAULT NULL COMMENT '薪水',
    job_id varchar(50) NULL DEFAULT NULL COMMENT '职位id',
    organization_id varchar(50) NULL DEFAULT NULL COMMENT '部门id',
    PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB

首先我们的解决思路是先查询所有员工的平均值
select avg(salary) from employee; -- 比如算出来的平均工资是5000
然后再select * from employee where salary > 5000按照这样的思路来查询。

虽然两步也可以达到想要的效果,但是实际却不会这么做,分两次请求不说,也增加了代码的复杂度,可以用子查询来解决。

子查询

  • 定义

在SQL中,子查询(subquery) 是指嵌套在其他语句(select、insert、update、delete、merge) 中的select语句;子查询中也可以嵌套另外一个子查询。

如果用子查询实现上面的查询:
select * from employee where salary > (select avg(salary) from employee);

  • 分类1
    根据子查询的返回可以分成三类子查询:
    标量子查询、行子查询、表子查询

  • 标量子查询:返回单个值(单行单列)的子查询,子查询可以替换成一个标量,比如上面的员工薪水就可以把平均值替换子查询语句。

select 后面可以使用标量子查询,比如我们想看看每个员工与平均工资之间的差距,只要是一个数值可以出现的地方,标量子查询都是可以使用的。

select first_name,
       last_name,
       salary,
       salary - (select ROUND(AVG(salary),0) from employee) as difference 
from employee;
  • 行子查询:返回包含一个或者多个列的单行结果(一行多列),标量子查询是行子查询的特例。

  • 表子查询:返回的是虚拟的表(多行多列),行子查询是表子查询的特例。表子查询可以当成一个数据表使用,from中的子查询,相当于创建了一个临时表,可以作为查询的一个数据源使用,mysql称之为派生表(derived table)。

比如下面的子查询:

-- 查询每个部门最高的工资
select o.name, -- 部门名称
       e.salary 
from organization o 
join (
        SELECT organization_id,
               max(salary) as salary 
        from employee 
        group by organization_id
    ) e 
on o.id = e.organization_id;
  • 分类2

子查询也可以根据子查询会不会引用外部查询的列分为 关联子查询非关联子查询。关联子查询查询时会引用外部查询的列,也就是里面的子查询不能单独执行,依赖于外部查询。没有引用外部查询的列就成为非关联子查询。

select job_id,
       first_name,
       last_name,
       salary
from employee e
where salary = (
    select max(salary)
    from employee i
    where i.job_id = e.job_id
);

比如上面的子查询 查询每个职位最高的薪水的员工信息

这个子查询的查询顺序是:

  1. 先取employ的第一条数据,取出job_id,first_name,last_name,salary字段
  2. 用取出的job_id字段作为条件,在去找employ中job_id等于刚取出的job_id中最大的salary,如果主查询中的salary不满足条件则舍去,满足则返回,这时的查询可以用上索引。
  3. 重复12,直至所有的记录都遍历完毕。

注意:在不考虑数据库对这个查询进行优化的前提下,里面的这个子句是每次都要执行的。

select max(salary)
    from employee i
    where i.job_id = e.job_id

也可以在select中用关联子查询,比如 查询每个部门的所有员工薪水总和

select o.name,
       (
          select sum(salary) 
          from employee e 
          where e.organization_id = o.id
        ) as total_salary
from organization o;

说到关联子查询也就不得不说 EXISTS 关键字,比如我们想查看部门里包含员工名字叫做David的部门

select o.name
from organization o
where exists (
    select * from employee e 
    where e.organization_id = o.id
    and e.first_name = 'David'
)

EXISTS只做存在性判断,如果里面的子查询有记录则外部的查询结果返回,否则舍去。NOT EXISTS和EXISTS相反,这里就不举例了。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 进阶7:子查询 /*含义:出现在其他语句中的select语句,称为子查询或内查询外部的查询语句,称为主查询或外查询...
    majorty阅读 8,120评论 0 1
  • 嵌套在其他语句内部的SELECT语句称为子查询或内查询,外面的语句可以是INSERT、UPDATE、DELETE、...
    程序员汪汪阅读 2,555评论 0 0
  • 1. 定义 出现在其他语句中的select语句称为子查询或内查询内部嵌套其他select语句的查询,称为外查询或主...
    舟渡的锅儿阅读 2,726评论 0 0
  • #子查询 /*含义:出现在其他语句内部的select语句,称为子查询或内查询 外部的查询语句,称为主查询或外查询 ...
    没错学习使我快乐阅读 1,558评论 0 0
  • #子查询 概念: 嵌套在另一个查询中的查询语句称为子查询,外部的查询称为主查询,类似于java中的内部类 语法 s...
    养仙女的猪阅读 1,274评论 0 0

友情链接更多精彩内容