SQL备忘--子查询与ALL/ANY运算符

概念

在SQL查询语句中包含了其他的查询语句,出现了SQL语句的嵌套,即为使用了嵌套子查询

子查询用法

子查询可以用在:

  • SELECT查询字段中
  • FROM表名语句中
  • WHERE条件中

由此可见子查询用法广泛,可用在SQL基本语句的每个位置。但具体每个位置的查询会有要求,下面具体说明

1. SELECT查询字段中

可直接用在select处的查询字段输出中,如下:

sql 复制代码
SELECT name as "老师姓名", 
(	
	SELECT AVG(s.score) 			-- 均分	
	FROM student s
	WHERE s.class = t.class		-- 此老师的班级
) as "学生平均分"
FROM teacher t

此时需注意:

  1. 子查询可以使用外部查询的字段,也就是和外部查询产生关联(关联子查询Correlated Subquery)
  2. 查询结果必须只有单个值(标量子查询Scalar Subquery),即不能出现多条数据,也不能出现多个列,否则会报错。本例通过AVG()函数确保只返回一个值
2. 在FROM表名语句中
sql 复制代码
SELECT t.name as "老师姓名", 
s.avg_score	as "平均分"
FROM teacher t,
(	
	SELECT class, AVG(score) as avg_score
	FROM student
	GROUP BY class
) s
WHERE t.class = s.class

此时注意点:

  1. 子查询可以使用外部查询的字段,也就是和外部查询产生关联,此时需要用 LATERAL关键字。本例中可以写为:

    SELECT t.name as "老师姓名",
    ss.avg_score as "平均分"
    FROM teacher t,
    LATERAL (
    SELECT AVG(s.score) as avg_score
    FROM student s
    WHERE t.class = s.class
    ) ss

仅Oracle、Mysql、PostgreSQL支持 LATERAL关键字

  1. 查询结果可以是单值,也可以是多条数据(集合)。若为多条数据时需要注意匹配,防止出现笛卡尔积的情况
3. 在WHERE条件中
sql 复制代码
SELECT *
FROM teacher t
WHERE class IN (	
	SELECT s.class 			-- 查找均分大于80分的班级		
	FROM student s
	WHERE s.class = t.class		-- 筛选有老师的学生班级
	GROUP BY s.class 
	HAVING AVG(s.score) > 80
)

此时需注意:

  1. WHERE子查询可以使用外部查询的字段,也就是和外部查询产生关联(关联子查询Correlated Subquery)
  2. 查询结果即可以为单个值(标量子查询Scalar Subquery),也可为一行数据(一行数据多列,行子查询Row Subquery)、多条数据(Table Subquery)。

单值时,外部可用=号判断子查询的结果。此时需确保查询结果不能出现多行或多列的情况,否则sql报错

单行数据时,外部也可以用=号判断子查询的结果,只是等号左边要写成多个数据在()内的格式

多行数据时,使用IN、或者ALL、ANY运算符来进行匹配,例如下例子

sql 复制代码
WHERE (class, grade) IN (	
	SELECT s.class , s.grade			
	FROM student s
	WHERE s.class = t.class	
	GROUP BY s.class, s.grade 
	HAVING AVG(s.score) > 80
)

子查询中的ALL、ANY运算符

SQL的子查询中,可能查询到多个结果,因此一般都用IN来匹配

sql 复制代码
SELECT *
FROM student
WHERE class IN (
	SELECT class 
	FROM teacher
	WHERE grade = 1
)

此时,可以通过比较运算符(=、!=、<、<=、>、>=)与ALL、ANY的组合,来表示等于、不等于、大于...集合中的全部数据

sql 复制代码
SELECT *
FROM student
WHERE class =ANY (		-- 查找属于1年级的学生
	SELECT class 
	FROM teacher
	WHERE grade = 1
)

ALL运算符相当于:对其中每个选项进行比较运算符计算 ,并用AND 运算符串联
IN运算符相当于:对其中每个选项进行=运算符计算 ,并用OR 运算符串联
ANY与IN类似,也是由OR运算符串联比较运算符写于ANY之前 ;如果是=ANY,则与IN相同

要注意

  • "=ALL"必然会返回NULL(除非后面的集合中只有一个元素值)。因为它等同于 c1 = "x1" AND c1 = "x2" AND c1 = "x3" ... ,当等式有两项及以上时,表中的每条数据带入此公式中,必然有被判断为FALSE的子项,导致整个判断为FALSE,数据被过滤掉
  • !=ANY必然返回所有结果(除非后面的集合中只有一个元素值)。因为它等同于 c1 != "x1 OR c1 != "x2" OR c1 != "x3" ...,当等式有两项及以上时,表中的每条数据带入此公式中,必然有被判断为TRUE的子项,导致整个判断为TRUE,使得数据被选择
sql 复制代码
SELECT *
FROM student
WHERE class !=ANY (		-- 查找不属于1年级所有班级的学生,设施
	SELECT class 
	FROM teacher
	WHERE grade = 1
)
相关推荐
吴声子夜歌3 分钟前
MongoDB 4.x——治理经验
数据库·mongodb
黄华SJ520it1 小时前
门店预约系统开发:提升服务行业数字化转型
前端·数据库·系统开发
万事可爱^1 小时前
Claude 新发布的 Opus 5,系统提示语删了 80%,半价还能逼近 Fable 5
android·服务器·数据库·人工智能·claude
早点睡啊Y2 小时前
深入学LangChain官方文档:Observability 与 Studio——先看清 Agent 到底做了什么
java·数据库·langchain
@insist1232 小时前
信息系统管理工程师-数据层知识点详解:存储、数据库与信息安全
数据库·软考·软件水平考试·信息系统管理工程师·软考信管
她说可以呀2 小时前
Redis集群
数据库·redis·缓存
Lorin 洛林2 小时前
为什么大模型总会“胡说八道“?一文彻底搞懂 RAG 知识库原理!
数据库
其实防守也摸鱼2 小时前
GitHub开源项目破圈方法论:从技术自嗨到生态共赢
服务器·数据库·学习·开源·github·命令行·linux系统
羑悻的小杀马特2 小时前
AI判不了设备异常?缺的不是算法,是这层数据底座
数据库·人工智能·ai
网安墨雨2 小时前
MySQL数据库 SQL语句详解
自动化测试·软件测试·数据库·python·sql·mysql