子查询在主查询前执行一次
创新互联建站2013年开创至今,公司以网站制作、成都网站制作、系统开发、网络推广、文化传媒、企业宣传、平面广告设计等为主要业务,适用行业近百种。服务企业客户上1000家,涉及国内多个省份客户。拥有多年网站建设开发经验。为企业提供专业的网站建设、创意设计、宣传推广等服务。 通过专业的设计、独特的风格,为不同客户提供各种风格的特色服务。
主查询使用子查询的结果
子查询要用括号括起来
将子查询放在比较运算符的右边
子查询中不要加ORDER BY子句
对单行子查询使用单行运算符 (如:=、、=、、=、)
对多行子查询使用多行运算符
ANY 指大于最小值
ANY指小于最大值
ALL 指大于最大值
ALL指小于最小值
#查询高于自己部门平均工资的员工名字,部门号,工资,平均工资*** 虚表
------------------------示例-----------------
#1.使用标准SQL嵌套子查询和连接查询两种方法查询选修课程名称为'gs'的学生学号和姓名
#2 使用标准SQL嵌套语句查询选修课程编号为‘2’的学生姓名和所属班级
#3.使用标准SQL嵌套语句查询选修全部课程的学员姓名和所属班级 *******
#4.查询选修了课程的学生人数
#5.查询选修课程超过3门的学员学号和所属班级 ****
-- 查询分类名称为手机数码的所有商品
1.查询分类名为手机数码的ID
SELECT cid FROM category WHERE cname='手机数码';
2.得出ID为1的结果
SELECT * FROM product WHERE cno = (SELECT cid FROM category WHERE cname='手机数码');
子查询练习:
子查询练习及答案:
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm DECIMAL(7,2),
deptno INT
) ;
INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
INSERT INTO emp VALUES(7981,'MILLER','CLERK',7788,'1992-01-23',2600,500,20);
CREATE TABLE dept(
deptno INT,
dname VARCHAR(14),
loc VARCHAR(13)
);
INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept VALUES(20, 'RESEARCH', 'DALLAS');
INSERT INTO dept VALUES(30, 'SALES', 'CHICAGO');
INSERT INTO dept VALUES(40, 'OPERATIONS', 'BOSTON');
--最高工资
SELECT MAX(sal) FROM emp;
--最少工资
SELECT MIN(sal) FROM emp;
--最高工资的员工信息
SELECT * FROM emp WHERE sal = (SELECT MAX(sal) FROM emp);
--最低工资的员工信息
SELECT * FROM emp WHERE sal = (SELECT MIN(sal) FROM emp);
-- 单行子查询( = = = )
-- 查询出高于10号部门的平均工资的员工信息
1.10号部门的平均工资
SELECT AVG(sal) FROM emp WHERE deptno = 10;
2. 高于上面结果员工信息
SELECT * FROM emp WHERE sal (SELECT AVG(sal) FROM emp WHERE deptno = 10);
-- 多行子查询(in not in any all) any all
-- 查询出比10号部门任何员工薪资高的员工信息
1. 查询出10号部门最高工资
SELECT MAX(sal) FROM emp WHERE deptno = 10;
2. 得出结果
SELECT * FROM emp WHERE sal (SELECT MAX(sal) FROM emp WHERE deptno = 10);
-- 查询出比10号部门任意一个员工薪资高的所有员工信息 : 只要比其中随便一个工资都可以
SELECT sal FROM emp WHERE deptno = 10;
-- 多列子查询(实际使用较少) in
-- 和10号部门同名同工作的员工信息
1. 查询出10号部门所有人 名字和工作
SELECT ename,job FROM emp WHERE deptno=10;
2. 得出结果
SELECT * FROM emp WHERE (ename,job) IN (SELECT ename,job FROM emp WHERE deptno=10) AND deptno !=10;
-- Select后面接子查询
-- 获取员工的名字和部门的名字
SELECT ename,deptno FROM emp ;
-- from后面接子查询
-- 查询emp表中所有管理层的信息
SELECT DISTINCT mgr FROM emp;
-- where 接子查询
-- 薪资高于10号部门平均工资的所有员工信息
1. 10号部门平均工资
SELECT AVG(sal) FROM emp WHERE deptno=10;
2. 得出结果
SELECT * FROM emp WHERE sal (SELECT AVG(sal) FROM emp WHERE deptno=10);
-- having后面接子查询
-- 有哪些部门的平均工资高于30号部门的平均工资
1. 统计所有的部门的平均工资
SELECT deptno, AVG(sal) FROM emp GROUP BY deptno;
2. 30号部门的平均工资
SELECT AVG(sal) FROM emp WHERE deptno=30;
3.得出结果:
SELECT deptno, AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal) (SELECT AVG(sal) FROM emp WHERE deptno=30);
-- 列出达拉斯加工作的人中,比纽约平均工资高的人
原文链接:
大概的形式是这样的:
下面还是以实例来说明,要不然不好理解,新建两张表,一张是商品表,另外一张是商品的评论表
商品表:
评论表:
然后插入一些数据:
下面我们用子查询的方式来查出商品的信息以及每个商品的评论数量
查询结果:
对于这种查询,可以分成两部来理解,首先忽略整个select子查询,查出商品表中的数据。
在结果字段中使用子查询的关键两点:
1.子查询只能返回一条数据,如果子查询返回多条数据则会出错。
2.每一条select子查询只能查询一个字段。
本篇开始是子查询的学习笔记,首先是一道题目:
where 型子查询,如果是 where 列 =(内层 sql) 则内层 sql 返回的必须是单行单列,单个值。
where 型子查询,如果是 where 列 in(内层 sql) 则内层 sql 返回的必须是单列,可以多行。
在学习 from 子查询之前,需要理解一个概念: 查询结果集在结构上可以当成表看 ,那就可以当成临时表对他进行再次查询:
exists 型子查询是指外层 sql 的结果,拿到内层 sql 去测试,如果内层 sql 成立,则该行取出。学习之前先建一张表:
向里面插入原来 ecshop.ecs_category 中的部分数据:
方法/步骤
1
首先,在一个查询中的查询结果作为外层查询的条件,可以用IN关键字,代码如下:
SELECT * FROM city WHERE CountryCode IN (SELECT Code FROM country);
如下图所示:
2
其次,外层查询的条件不在内层查询结果,可以用NOT IN关键字,代码如下:
SELECT * FROM city WHERE CountryCode NOT IN (SELECT Code FROM country);
如下图所示:
3
使用EXISTS关键字查询时,内层查询语句不返回查询的记录,而是返回一个Boolean值;当内层查询返回的值为true时,外层查询语句将进行查询,如果返回false时,将不进行查询或查询结果为空,代码如下:
SELECT * FROM city WHERE EXISTS (SELECT Name FROM country);
如下图所示:
4
由第三步可知,与EXISTS相对的是NOT EXISTS,当内层查询返回的值为false时,外层查询语句将进行查询,如果返回true时,将不进行查询或查询结果为空,代码如下:
SELECT * FROM city WHERE NOT EXISTS (SELECT Name FROM country);
如下图所示:
5
满足其中的任一条件,就可以通过该条件来执行外层查询语句,用关键字ANY,代码如下:
SELECT * FROM city WHERE Population = ANY (SELECT Population FROM country);
如下图所示:
6
子查询还包含比较运算符,有“="、“="、"!="等关键字,代码如下:
SELECT * FROM city WHERE Population = (SELECT Population FROM country WHERE Name = 'Afghanistan');
SELECT * FROM city WHERE Population = (SELECT Population FROM country WHERE Name = 'Afghanistan');
SELECT * FROM city WHERE Population != (SELECT Population FROM country WHERE Name = 'Afghanistan');
如下图所示:
7
满足所有条件,只有满足内层查询语句返回所有结果,代码如下:
SELECT * FROM city WHERE Population = ALL (SELECT Population FROM country WHERE Name = 'Afghanistan');
如下图所示:
举例二:查询xs表中名字包含下画线的学生学号和姓名。
举例二:查询xs表中专业名为“计算机”、“通信工程”或“无线电”的学生的情况。
解释!!!(超重要) :
(1)先执行where查询语句中的子查询,得到了选修课程号为206的所有学生的学号集( IN子查询只能返回一列数据 ,这里的in子查询得到了一个只含有学号列的表,对于比较复杂的查询,可以使用嵌套的子查询);
(2)然后再进行外查询,对xs中的每条记录,判断其学号字段值是否在前面所求的学号集合中,在!IN谓词会返回True,将此记录的姓名、学号值取出作为where的结果集的一行,不在!IN谓词返回False,继续处理下一条记录;
(3)对xs表筛选处理完成后,将最终结果集进行显示。
举例二:查找xs表中比所有计算机系的学生年龄都大的学生学号、姓名、专业名、出生日期。
举例三:
查找xs_kc表中课程号206的成绩不低于课程号101的最低成绩的学生的学号。
解释:
(1)本例子在子查询的条件中使用了限定形式的列名引用xs.学号,表示这里的学号列出自表xs;
(2)前面的例子中,内层查询只处理一次,得到一个结果集,在依次处理外层查询;而本例子的内层查询要处理很多次,因为xs.学号列有不同的学号值;
(3)这类子查询称为相关子查询,因为子查询的条件依赖于外层查询中的某些值;
(4)处理过程:首先查找外层查询中xs表的第一行,根据该行的学号列值处理内层查询,若结果不为空,则where条件就为真,就把该行的姓名值取出来作为结果集的一行;然后再找xs表的第2、3、...行,重复上述处理过程,直到xs表的所有行都查找完为止。
mysql区分了四种类型的子查询:表子查询、行子查询、列子查询、标量子查询。