打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SQL语句多表数据查询之第4篇:子查询

所谓的子查询,就是将一个select语句所得到的查询结果再次用于select语句中。实际工作中,子查询一般用于三种场合。

作为“表”使用

任何一个select语句在用“()”进行分割之后,都可以再次作为“表”来使用。例如,上一篇文章《SQL语句多表数据查询之第3篇:子集、补集和差集》中的select语句采用的就是这种方法:

select * from

(select * from 订单 A left join 客户 B on A.客户id = B.客户id

union

select * from 订单 A right join 客户 B on A.客户id = B.客户id)

where A.客户id is null or B.客户id is null

上述语句中用括号包起来的部分,就是Access中用于生成多表并集数据的语句。简单的说,就是先左连、再右连、最后再合并起来。如果用的是SQLServer数据库,可以改用Full Join,就会更加简单。

这里用括号包起来的SQL语句所得到的查询结果,再次用于select时就相当于一个数据表了,此时再做的任何查询都是基于该查询所作的二次查询。

作为“列字段”使用

例如:

select 产品id,(select sum(数量) from 订单) as 总量,数量 from 订单

预览效果如下图。

由于子查询在作为“列字段”使用时,只能返回一个字段的值。当需要进行一些复杂的数据处理时,可以将子查询同时作为“表”和“列字段”使用。例如,我们要实现按总量排名的效果,可以将以下子查询同时用于“列字段”和“表”中:

select 产品id,sum(数量) as 总量 from 订单 group by 产品id

为了更清晰的看到select语句结构,我们将这个子查询语句以SUB代替:

select *,(select count(产品id) from (SUB) A where A.总量>B.总量) as 排名 from (SUB) B

预览效果如下图。

如要按总量从低到高排序,可以在第二个SUB语句的后面加上:order by sum(数量) desc。

作为“查询条件”使用

将子查询用于where中,是子查询最常使用的方法。

例如,获取订单表中单价高于总体均价的数据记录:

select * from 订单 where 单价 > (select avg(单价) From 订单)

再如,要列出产品表中订单数量大于等于两条的数据记录,必须通过订单中的子查询来实现,这是因为产品表中仅记录了产品名称等信息,并没有具体的订单数据:

select * from 产品 A where (select count(*) from 订单 B where A.产品id = B.产品id) >= 2

由此可见,当把子查询用作“查询条件”时,其返回值也只能是一列的值。当需要使用多列时,可将其组合在一起返回,例如A列+B列+C列,也可以在where中使用and或or连接多个条件。

通过子查询获取多表之间的差集

如下图所示,交集中“客户id”的值有C01、C03和C04,并集中还有C02、C05和C08。只要将交集中的值排除掉,剩下的不就是差集了吗?

也就是:并集-交集=差集。

按照常规的写法,select语句可以这样:

select * from (SQL并集语句) where A.客户id not in ('c01','c03','c04') or B.客户id not in ('c01','c03','c04')

可问题是,这里的C01、C03和C04并不是固定的,它们会随着数据录入的增加、修改或删除而发生变化。数据调整了,两个表得到的交集肯定也会调整。因此,要想动态获取条件判断中的比较值,最好的方法还是使用子查询。

例如,要获取订单表和客户表中都存在的“客户id”值的sql语句是:

select A.客户id from 订单 A inner join 客户 B on A.客户id = B.客户id

由于该语句得到的是两个表的交集,因此,在获取“客户id”时,指定其来源于A表或B表,效果都是一样的。

假如将这个子查询语句以subSQL表示,那么,获取差集的select语句完整写法如下:

select * from (SQL并集语句) where A.客户id not in (subSQL) or B.客户id not in (subSQL)

最终得到的查询结果刚好就是上图所标示的差集部分。预览效果如下图。

这个select语句看起来虽然有点复杂,但逻辑非常简单。

除了IN之外,使用EXISTS也能实现类似的效果。它们的区别在于:IN中用到的select语句必须有具体的返回值,而EXISTS不需要,因为EXISTS判断的是是否存在指定的记录。如下图。

由于EXISTS用到的子查询中同样使用了订单表和客户表,为了避免和前面的并集语句相冲突,这里的别名分别使用C和D来表示。

如果觉得这个语句有点复杂,可以再看看下面这个简单的例子:

这里的EXISTS同样使用“客户id”进行判断。由于客户表中不存在内容为C08的记录,因而得到的查询结果中会自动将该行剔除。

需要特别强调的是,当使用EXISTS时,子查询中必须使用where语句将子查询与主表或主查询关联起来,否则将无法起到任何效果。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
MySQL必知必会--使用子查询
如何用sql语句查一张表的一部分和另一张表的全部呢
MySql-Day-02
3掌握SQL,学习这30个实例就足够了
MySQL索引优化分析
mysql last_insert_id
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服