MySQL子查询(标量、行、列、表)分页查询 联合查询


一、子查询


1.子查询的定义

  • 定义: 出现在其他语句中的select语句,称为子查询或者内查询.

  • 外部的语句可以是insert,update,delete,select,如果外面为select语句,则称为外查询或者主查询.

2.子查询的分类

1.按子查询出现的位置分:
    select后面
            仅支持标量子查询
    from后面
            支持表子查询
    'where或having后面' 
            '标量子查询' (用的最多)
            '列子查询'   (用的较多)
            '行子查询'
    exists后面(相关子查询)
            表子查询

2.按结果集的行列数不同分:
    标量子查询 (结果集只有一行一列)
    列子查询 (结果集只有一列多行)
    行子查询 (结果集有一行多列)
    表子查询 (结果集有多行多列)

3. 标量子查询

特点:
1.子查询放在小括号内.
2.子查询一般放在条件的右侧.
3.标量子查询,一般搭配单行操作符使用.
> < >= <= = <>
4.列子查询,一般搭配着多行操作符使用.
in any/some all
5.子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果.

# 1.标量子查询
案例1:查询员工表中谁的工资比Tom高?
a)查询Tom的工资
select 工资
from 工资表
where name='Tom'

b)查询员工信息,满足工资> "a)查询"的结果
select * 
from 工资表
where 工资>(
      select 工资
      from 工资表
      where name='Tom'
);



4. 列子查询 (多行子查询)


其中any|some很少用,大多情况下可以用 min()或max()替代
其中all也很少用,大多情况下可以用 max()或max()替代

返回区域id是1400或1700的部门中所有员工的姓名
1.先查询区域id是1400或1700的所有部门编号
select distinct 部门id
from 部门表
where 区域id in(1400,1700);
2.查询员工姓名,其部门号在上面的结果列表1中
select name
from 员工表
where 部门id in(
    select distinct 部门id
    from 部门表
    where 区域id in(1400,1700);
);

#上例中 in 也可以用 =any 来替代
select name
from 员工表
where 部门id =any(
    select distinct 部门id
    from 部门表
    where 区域id in(1400,1700);
);

# 同理 not in 也可以用 <>all 替代

5.行子查询 (结果集为一行多列)

这种方式很少使用.

例子: 查询员工id最小并且工资也是最高的员工信息
1.查询最小员工id
select min(员工id)
from 员工表;

2.查询最大员工工资
select max(工资)
from 员工表;

3.查询符合1和2的员工信息
select *
from 员工表
where 员工id=(
        select min(员工id)
        from 员工表
)
and 工资=(
        select max(工资)
        from 员工表;
);

#使用行子查询方式完成上例
select * 
from 员工表
where (员工id,工资)=(
        select min(员工id),max(工资)
        from 员工表
);

二、在不同位置后的使用方法

1.放在select后面

# 仅支持标量子查询(子查询结果为一行一列)

1. 查询每个部门的员工个数
select b.*,(
        select count(*)
        from 员工表 a
        where a.部门id=b.部门id
) 员工个数
from 部门表 b;

2.放在from后面

#将子查询的结果充当一张表,要求必须起别名.

例子: 查询每个部门的平均工资的工资等级
1.查询每个部门的平均工资
select avg(工资),部门id
from 员工表
group by 部门id

2.连接1的结果集和工资等级表,筛选条件为平均工资在最第工资和最高工资之间对应的工资等级.
select ag_1.*,g.工资等级
from (
        select avg(工资) ag,部门id
        from 员工表
        group by 部门id
)ag_1
inner join 工资等级表 g
on ag_1.ag between 最高工资 and 最低工资;

3.放在exists后面 (相关子查询)

#使用exists查询结果是否存在,存在为1.不存在为0
select exists(select 员工id from 员工表);
结果为1

例如: 查询所有有员工的部门名
select 部门名
from 部门表 d
where exists(
        select *
        from 员工表 a
        where d.部门id=a.部门id
);

===========================================
!!!!#!!exists方式和前几种子查询顺序不同,它是: 先做查询select 部门名 from 部门表 d得到结果,然后再去select * from 员工表 a where d.部门id=a.部门id进行过滤得到最终结果.

三、分页查询

1.分页查询语法及使用

应用场景:当要显示的数据一页显示不全的时候,需要分页提交sql请求.

语法:
select 查询列表
from 表
[join_type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后筛选
order by 排序的字段]
limit offset,size;

# offset要显示条目的起始索引(从0开始)
size要显示的条目个数.

#分页查询公式:
select 查询列表
from 表
limit (page-1)*size,size;

例如: 查询工资表前5条.(两种方式,0可省略)
select * from 工资表 limit 0,5;
select * from 工资表 limit 5;

例如: 查询工资表第11到25条.
select * from 工资表 limit 10,15;

2.分表查询效率

当分表查询的limit起始位置增大的时候.扫描的数据量也会越多,速度就会越慢.例如:
mysql> select * from emp limit 0,5;
...
5 rows in set (0.00 sec)

mysql> select * from emp limit 900000,5;
...
5 rows in set (0.43 sec)

# 解决方案1: 记录当前页的最大或最小id
select * from emp where id>=900000 limit 5;
...
5 rows in set (0.01 sec)
select * from emp where id<900000 order by id desc limit 5;

# 解决方案2: (但是必须是连续的id,否则可能数据量不能和页面要求匹配)
mysql> select * from emp where id between 910000 and 910005;
6 rows in set (0.00 sec)

3.查询练习

https://www.bilibili.com/video/BV12b411K7Zu?p=98 参考答案及讲解.

https://www.bilibili.com/video/BV12b411K7Zu?p=99 参考答案及讲解.


四、联合查询

将多条查询语句的结果合并成一个结果.可以支持多个union
select * from 工资表 where email like '%a%' or 部门id>90;
相当于下条命令
select * from 工资表 where email like '%a%'
union
select * from 工资表 where 部门id>90;

应用场景
要查询的结果来自于多个表,且多个表没有连接关系,但查询的信息一致或非常接近.

#1.所以多条查询语句的查询列数是一致的.
#2.多条查询语句的列数类型.顺序和意义是一致的.
#3.使用union会自动去重.如果不去重要使用union all

=============================
1. select * from t表 where id=1 or id=10000;

2. select * from t表 where id=1
   union
   select * from t表 where id=10000;

# 有索引大数据量的情况下,2的执行效率比1要高很多。
Copyright © 2009 - Now . XPBag.com . All rights Reserved.
夜心的小站 » MySQL子查询(标量、行、列、表)分页查询 联合查询

提供最优质的资源集合

立即查看 了解详情