mysql中select子查(select中的select子查询)询探索

mysql中select子查询探索

表结构

emp

+--------------+---------------+------+-----+-------------------+-----------------------------+
| Field        | Type          | Null | Key | Default           | Extra                       |
+--------------+---------------+------+-----+-------------------+-----------------------------+
| empno        | int(10)       | NO   | PRI | NULL              | auto_increment              |
| ename        | varchar(50)   | YES  | MUL | NULL              |                             |
| job          | varchar(100)  | YES  |     | NULL              |                             |
| mgr          | int(10)       | YES  | MUL | NULL              |                             |
| hiredate     | datetime      | YES  | MUL | NULL              |                             |
| sal          | decimal(10,2) | YES  | MUL | NULL              |                             |
| comm         | decimal(10,2) | YES  |     | NULL              |                             |
| deptno       | int(11)       | YES  |     | NULL              |                             |
| created_time | datetime      | YES  |     | CURRENT_TIMESTAMP |                             |
| updated_time | datetime      | YES  |     | NULL              | on update CURRENT_TIMESTAMP |
| is_deleted   | tinyint(1)    | YES  | MUL | 0                 |                             |
| version      | int(1)        | YES  |     | 1                 |                             |
+--------------+---------------+------+-----+-------------------+-----------------------------+

dept

+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| deptno | int(11)     | NO   | PRI | NULL    | auto_increment |
| dname  | varchar(10) | YES  |     | NULL    |                |
| loc    | varchar(50) | YES  |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+

数据

mysql> select * from emp where empno =1;
+-------+--------+------+------+---------------------+------+-------+--------+
| empno | ename  | job  | mgr  | hiredate            | sal  | comm  | deptno |
+-------+--------+------+------+---------------------+------+-------+--------+
|     1 | 张无忌 | 教主 | NULL | 1981-11-17 00:00:00 | NULL | 20.00 |      4 |
+-------+--------+------+------+---------------------+------+-------+--------+
1 row in set (0.24 sec)
mysql> select * from dept where deptno =4;
+--------+-------+------+
| deptno | dname | loc  |
+--------+-------+------+
|      4 | 运营  | 杭州 |
+--------+-------+------+
1 row in set (0.08 sec)

select 中的子查询

mysql>  select ename,(select dname from dept d where e.deptno = d.deptno) as dname from emp e where empno = 1;
+--------+-------+
| ename  | dname |
+--------+-------+
| 张无忌 | 运营  |
+--------+-------+
1 row in set (0.07 sec)

执行计划

mysql> explain select ename,(select dname from dept d where e.deptno = d.deptno) as dname from emp e where empno = 1;
+----+--------------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type        | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+--------------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | PRIMARY            | e     | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
|  2 | DEPENDENT SUBQUERY | d     | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+--------------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
2 rows in set (0.24 sec)

疑惑

ChatGPT给出的执行过程

功能是查询员工编号为1的员工姓名和所在部门名称。它的执行过程如下:1. 从emp表中查询员工编号为1的员工记录。
2. 对于查询结果中的每一条记录,都会执行一个子查询,查询该员工所在的部门名称。这个子查询使用了dept表,通过员工表和部门表的deptno字段关联,查询出员工所在部门的名称。由于是子查询,所以需要在执行每一个子查询的时候都扫描一遍dept表,效率相对较低。
3. 将员工姓名和部门名称返回给用户。总体来说,这条SQL语句虽然可以实现查询员工姓名和部门名称的功能,但是由于使用了子查询,效率相对较低,没有充分利用索引,而且在数据量较大时容易出现性能问题。如果想要优化这条SQL语句,可以考虑使用JOIN操作来代替子查询,这样可以更好地利用索引,提高查询效率

思考

通过执行计划可以看出,先执行的是DEPENDENT SUBQUERY这部分(id大的优先执行),也就是select dname from dept d where e.deptno = d.deptno但是这部分是不能单独执行的,所以猜测mysql对这部分做了处理,处理成类似这种select d.dname,e.deptno from dept d join emp e on d.deptno = e,deptno,生成了一个临时表,然后再执行主表和临时表的连表查询(临时表的意思是啥?比如dept表有很多列,同时又很多行,其中还有一大部分不满足d.deptno = e,deptno这个条件,此时临时表相对于对大表做了一个精简)

当我把以为告诉ChatGPT的时候他是这么说的

非常抱歉,我的回答可能存在一些歧义。实际上,第一条SQL语句的执行顺序是这样的:执行子查询,查询出员工所在的部门名称。这个子查询使用了dept表,通过员工表和部门表的deptno字段关联,查询出员工所在部门的名称。执行主查询,查询员工姓名和部门名称。这个查询使用了emp表,通过员工表的empno字段和where条件过滤,查询出员工姓名和部门名称。在执行子查询的时候,子查询中的e.deptno是来自于主查询中的emp表,是通过where条件过滤出来的,所以子查询中的e.deptno是一个固定的值。子查询的结果会作为一个临时表,与主查询中的emp表进行连接查询,最终得到员工姓名和部门名称的查询结果。总的来说,第一条SQL语句使用了子查询,虽然可以实现查询员工姓名和部门名称的功能,但是效率不高,不够优化。而第二条SQL语句使用了JOIN操作,可以更好地利用索引,提高查询效率。

到这里对于select子查询的执行顺序更迷惑了,不知道DEPENDENT SUBQUERY到底时怎么执行的,到底有没有生产临时表,但是可以明确这种子查询的效率不如join好

注意事项

在select子查询中,子查询不能返回多行数据

mysql> select * from emp where deptno = 3;
+-------+----------+----------+-----+---------------------+------+------+--------+
| empno | ename    | job      | mgr | hiredate            | sal  | comm | deptno | 
+-------+----------+----------+-----+---------------------+------+------+--------+
|     2 | 紫衫龙王 | 护教法王 |   1 | 1981-06-09 00:00:00 | NULL | NULL |      3 | 
|     3 | 白眉鹰王 | 护教法王 |   1 | 1981-04-02 00:00:00 | NULL | NULL |      3 | 
|     4 | 金毛狮王 | 护教法王 |   1 | 1981-05-01 00:00:00 | NULL | NULL |      3 | 
|     5 | 青翼蝙王 | 护教法王 |   1 | 1980-12-17 00:00:00 | NULL | NULL |      3 | 
+-------+----------+----------+-----+---------------------+------+------+--------+
4 rows in set (0.08 sec)

子查询返回多条数据的情况

mysql> select d.dname,(select e.ename from emp e where e.deptno = d.deptno ) from dept d where d.deptno = 3;
Subquery returns more than 1 row

子查询中的limit

mysql> select d.dname,(select e.ename from emp e where e.deptno = d.deptno limit 1) from dept d where d.deptno = 3;
+-------+---------------------------------------------------------------+
| dname | (select e.ename from emp e where e.deptno = d.deptno limit 1) |
+-------+---------------------------------------------------------------+
| 市场  | 紫衫龙王                                                      |
+-------+---------------------------------------------------------------+
1 row in set (0.26 sec)

select子查询中除了使用limit还可以使用order by,根据某种条件排序返回第一个或者最后一个

mysql> select d.dname,(select e.ename from emp e where e.deptno = d.deptno order by e.empno desc limit 1) from dept d where d.deptno = 3;
+-------+-------------------------------------------------------------------------------------+
| dname | (select e.ename from emp e where e.deptno = d.deptno order by e.empno desc limit 1) |
+-------+-------------------------------------------------------------------------------------+
| 市场  | 青翼蝙王                                                                            |
+-------+-------------------------------------------------------------------------------------+
1 row in set (0.09 sec)

select子查询可能的使用场景

  1. 带统计的查询

查询部门名称,地点,和部门人数

mysql> select dname,loc,(select count(empno) from emp e where e.deptno = d.deptno) as count from dept d;
+-------+------+-------+
| dname | loc  | count |
+-------+------+-------+
| 开发  | 北京 |    10 |
| 测试  | 上海 |     3 |
| 市场  | 广州 |     4 |
| 运营  | 杭州 |     1 |
+-------+------+-------+
4 rows in set (0.09 sec)
  1. 主查询对应的子查询是多行,主查询只需要一行,例如查询部门名称,所在地,和部门中id最大的一个人的名称
mysql> select d.dname,(select e.ename from emp e where e.deptno = d.deptno order by e.empno desc limit 1) from dept d where d.deptno = 3;
+-------+-------------------------------------------------------------------------------------+
| dname | (select e.ename from emp e where e.deptno = d.deptno order by e.empno desc limit 1) |
+-------+-------------------------------------------------------------------------------------+
| 市场  | 青翼蝙王                                                                            |
+-------+-------------------------------------------------------------------------------------+
1 row in set (0.09 sec)
  1. 其他暂时也没想到,工作里面一般能join就不select子查询,之所以想到探索select子查询,是因为公司里面不少这种写法,当初第一感觉挺新奇,是不是这种效率更好?于是就有了select子查询探索之旅,后续继续在完善select子查询的执行流程,也不知道是我误导了ChatGPT还是他迷糊了我,总觉得他是墙头草,说的不靠谱

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/840023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

民国漫画杂志《时代漫画》第18期.PDF

时代漫画18.PDF: https://url03.ctfile.com/f/1779803-1248612707-27e56b?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络!

THunt:免费助力跨境电商

Temu是什么? Temu是一个专注于跨境电商的在线平台,帮助卖家了解什么是热门产品。 THunt 您可以使用THunt快速比价,快速评估卖家信誉,最大化您的利润空间!您还可以更好地了解竞争格局并做出更具竞争力的决策。 Thunt…

春秋CVE-2022-23906

简介 CMS Made Simple v2.2.15 被发现包含通过上传图片功能的远程命令执行 (RCE) 漏洞。此漏洞通过精心制作的图像文件被利用。 正文 1.进入靶场2.进入登录界面,弱口令admin/123456 3.进入后台,文件上传点 4.上传一句话木马图片 5.复制图片&#xf…

细胞冻存——让你的细胞“长生不老”

《星际穿越》电影中提到漫长的太空旅程中,宇航员可以进入休眠水床休眠,并自行设定唤醒时间。在《异形》《深空失忆》《三体》等科幻作品中,都出现此类技术。《三体》中,休眠后来成为人类最普遍的一项技术。技术上的人类低温休眠&a…

huggingface的load_dataset()函数

第一种:从huggingface官网加载: from datasets import load_dataset dataset load_dataset(pathsquad, splittrain)path等于相关数据集的名字就能下载并加载相关数据集 第二种:从本地加载数据集 用path参数指定数据集格式 json格式&…

OpenCV:入门(五)

图像梯度 图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯度值也 较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。一般情 况下,图像梯度计…

剖析并实现C++17新特性的Any类型

问题: 对于这样的场景:对于一些CS(客户端-服务端)模型,当用户在客户端传入相应的事件时,我们需要实现框架即在服务端去分配线程处理这些事件,即调用用户的事件处理函数,那么对于不同…

中文信息期刊投稿邮箱

《中文信息》杂志是国家新闻出版总署批准的国家级刊物(月刊),国内外公开发行,大十六开印刷。本刊主要反映我国中文信息处理的学术水平,重点刊登科技、经济、教育等领域的基础理论、科研与应用技术的学术论文&#xff0…

Rust:如何使用 Pytorch 深度学习模型?

以下笔记内容仅供参考,尚未进行实际验证。 在Rust中使用PyTorch通常涉及使用一个称为tch的第三方crate,它是PyTorch的C API的Rust绑定。下面是一个简单的例子,展示了如何在Rust程序中加载一个PyTorch模型并进行预测。 首先,你需要…

第2天 搭建安全拓展_小迪网络安全笔记

1.常见搭建平台脚本使用: 例如 phpstudy IIS Nginx(俗称中间件): 什么是中间件: 中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用&#…

vue2引入brand.vue和brand-add-or-update.vue后重启项目报错解决方案

最近在用粒谷商城项目练手,学习到P59时引入品牌两个vue文件,重启(npm run dev)项目报错: ERROR Failed to compile with 2 errors 12:11:59Th…

前端调用浏览器录音功能且生成文件(vue)

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; 首先在页面中给两个按钮&#xff0c;分别是“开始录音”&#xff0c;“结束录音”。以及录音成功后生成一个下载语音的链接。 1. 先看页面展示 <template><div><button click"startRecording…

【论文阅读】Rank-DETR(NIPS‘23)

paper:https://arxiv.org/abs/2310.08854 code:https://github.com/LeapLabTHU/Rank-DETR

Go 生成UUID唯一标识

什么是UUID 通用唯一识别码&#xff08;英语&#xff1a;Universally Unique Identifier&#xff0c;简称UUID&#xff09;是一种软件建构的标准&#xff0c;亦为自由软件基金会组织在分散式计算环境领域的一部份。 UUID的目的&#xff0c;是让分散式系统中的所有元素&#x…

微信小程序视频怎么保存到本地

你是否遇到过在微信小程序中发现了精彩的视频&#xff0c;却不知道如何将其保存到本地的困扰&#xff1f;别担心&#xff0c;这篇文章将为您揭示2024年最新的保存方法&#xff0c;让您轻松下载和保留这些珍贵的视频内容。不管您是使用安卓设备还是苹果设备&#xff0c;我们都为…

SD3303A大功率高精度LED驱动芯片3W低功耗高效率工作温度40c+85%

SD3303A是一款大功率高亮度LED驱动芯片&#xff0c;可以提供 1A的电流驱动3W的LED。具有高效率&#xff0c;低功耗等特点 &#xff0c;适用于电池供电的LED照明设备。 SD3303A具有开路保护和过温保护。 SD3303A需要使用两颗10uF(或者更大)的瓷 片电容&#xff0c;来保证电路性能…

学生手机管理方案

咱们现在的学生&#xff0c;手机几乎成了标配。所以问题就来了&#xff0c;怎么管理这些手机&#xff0c;让手机在课堂上不成为学习的干扰&#xff1f; 先得搞明白&#xff0c;手机在学生手里上该扮演什么角色。手机确实能帮学生查资料、交流学习&#xff0c;甚至写作业&#x…

Log360:护航安全,远离暗网风险

暗网有时候就像是一个神秘的地下世界&#xff0c;是互联网的隐蔽角落&#xff0c;没有任何规则。这是一个被盗数据交易、网络犯罪分子策划下一步攻击的地方。但仅仅因为它黑暗&#xff0c;不意味着你要对潜在的威胁视而不见。 暗网 这就是ManageEngine Log360的用武之地&…

用Visual Studio进行Qt开发的Cmake模板

使用Visual Studio进行Qt开发的时候&#xff0c;我们可以借用Cmake的moc功能和相应对Qt的支持生成VS工程。 文件组织 Root │ cmake.sh // cmake执行脚本 │ CMakeLists.txt // 根目录cmake文件 │ README.md │ text.txt ├─bin …

【Oracle篇】rman工具实用指南:常用命令详解与实践(第二篇,总共八篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…