hincky的主页 hincky的主页
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)

Hincky

当有趣的人,做想做的事
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)
  • 数据库

    • sql

      • SQL快查
        • 语句顺序
        • 执行顺序
        • like用法
        • 最值
        • 特殊
        • 子查询
        • 关键字
      • 数据语言
        • DDL 数据定义语言
          • 对库定义
          • 对表定义
        • DML
        • DCL
        • DQL
      • select查询
        • select语句sql关键字顺序
        • sql语句实际执行顺序
        • 提升查询效率的方法
      • where条件查询
        • 比较运算符
        • 逻辑运算符
        • like + 通配符 (小心索引失效)
        • 分组
      • 函数
        • 聚合函数
        • 算术函数
        • 字符串函数
        • 日期函数
        • 转换函数
      • 分组查询
      • 子查询
        • 关联子查询
        • 非关联子查询
        • 集合比较子查询
          • IN 和 EXISTS 如何选择
          • NOT IN 和 NOT EXISTS 如何选择
        • 子查询作为计算字段
      • 多表查询
        • 交叉连接
        • 等值与自然连接
        • 非等值连接
        • 左连接
        • 右连接
        • 自连接
      • 牛客网题目整合
    • MySQL开发规范

    • mysql

    • MySQL调优

    • kafka

  • 网络协议以及抓包工具

  • Git笔记

  • 技术分享

  • Oauth2

  • 计算机相关技术
  • 数据库
  • sql
hincky
2022-10-29
目录

子查询

# 子查询

  • 关联子查询:主句查询条件和从句查询条件进行了关联,外部执行一次里面就执行一次
  • 非关联子查询:从句计算的结果是固定的,外部查询依赖里面查询的结果
  • 集合比较子查询

# 关联子查询

对于外部查询返回的每一行数据,内部查询都要执行一次。另外,在关联子查询中是信息流是双向的。外部查询的每行数据传递一个值给子查询,然后子查询为每一行数据执行一次并返回它的记录。然后,外部查询根据返回的记录做出决策。

一般搭配:

  1. 从句里面一般都有类似 WHERE a.team_id = b.team_id 的语法
SELECT player_name, height, team_id FROM player AS a WHERE height > (SELECT avg(height) FROM player AS b WHERE a.team_id = b.team_id)
1
  1. 和 EXISTS/NOT EXISTS 一起来使用

EXISTS 子查询用来判断条件是否满足,满足的话为 True,不满足为 False。

SELECT player_id, team_id, player_name FROM player WHERE EXISTS (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)
1

# 非关联子查询

  1. 先执行内层查询
  2. 再执行外层查询

外层查询依赖内层的查询结果

SELECT player_name, height FROM player WHERE height = (SELECT max(height) FROM player)
1

# 集合比较子查询

ANY、ALL 关键字必须与一个比较操作符一起使用

因为如果你不使用比较操作符,就起不到集合比较的作用,那么使用 ANY 和 ALL 就没有任何意义。

比较类型 作用 例句
IN 判断是否在集合中 SELECT player_id, team_id, player_name FROM player WHERE player_id in (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)
ANY 与子查询返回的任何值比较 SELECT player_id, player_name, height FROM player WHERE height > ANY (SELECT height FROM player WHERE team_id = 1002)
ALL 与子查询返回的所有值比较 SELECT player_id, player_name, height FROM player WHERE height > ALL (SELECT height FROM player WHERE team_id = 1002)
SOME 与ANY作用相同,一般用ANY

# IN 和 EXISTS 如何选择

SELECT * FROM A WHERE cc IN (SELECT cc FROM B)

SELECT * FROM A WHERE EXIST (SELECT cc FROM B WHERE B.cc=A.cc)
1
2
3

在这里例子当中,表 A 指的是 player 表,表 B 指的是 player_score 表。

在对 cc 列建立索引的情况下,我们还需要判断表 A 和表 B 的大小。

如果表 A 比表 B 大,那么 IN 子查询的效率要比 EXIST 子查询效率高,因为这时 B 表中如果对 cc 列进行了索引,那么 IN 子查询的效率就会比较高。

如果表 A 比表 B 小,那么使用 EXISTS 子查询效率会更高,因为我们可以使用到 A 表中对 cc 列的索引,而不用从 B 中进行 cc 列的查询。

总结

  1. 都是对较小的表进行索引,提高查询效率;
  2. 小表在后(内层),用 IN
  3. 小表在前(外层),用 EXISTS

IN表是外边和内表进行hash连接,是先执行子查询。 EXISTS是对外表进行循环,然后在内表进行查询。 因此如果外表数据量大,则用IN,如果外表数据量小,也用EXISTS。

# NOT IN 和 NOT EXISTS 如何选择

IN有一个缺陷是不能判断NULL,因此如果字段存在NULL值,则会出现返回,所以最好使用NOT EXISTS。

# 子查询作为计算字段

比如想查询每个球队的球员数

SELECT team_name, (SELECT count(*) FROM player WHERE player.team_id = team.team_id) AS player_num FROM team
1

将子查询SELECT count(*) FROM player WHERE player.team_id = team.team_id作为了计算字段

通常我们需要给这个计算字段起一个别名,这里我用的是 player_num,因为子查询的语句比较长,使用别名更容易理解。

编辑 (opens new window)
#SQL
分组查询
多表查询

← 分组查询 多表查询→

最近更新
01
人生前期重要的能力
05-17
02
防火墙命令
04-11
03
docker-compose部署mysql主从集群
03-22
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Hincky | MIT License | 粤ICP备2022120427号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式