8.4 数据库的高级查询


目录

[toc]


一、课程介绍

1.数据的统计分析:

汇总函数(全表范围),分组查询、HAVING子句

2.多表连接查询

内连接、外连接

3.子查询

嵌套查询:单行子查询,多行子查询;

WHERE子查询、FROM子查询、SELECT子查询

二、汇总函数

又叫聚合函数。

2.1 作用

简单的数据统计。

在查询分析中,应用广泛:可以对数据进行求和、求最大值和最小值、求平均值等。

特点:

  • 默认情况下,统计范围是整个数据表。
  • 返回的结果集中,只有一条记录。

汇总函数一共有5个,逐一介绍:

2.2 分类

1.SUM函数

1.用途:

SUM函数求和的对象只能是数字型。因为如果是字符型,统计结果为0;如果是日期型,统计结果是毫秒数相加。

2.案例演示:

SELECT SUM(sal) FROM t_emp WHERE deptno IN(10,20);        # sal是整数型

结果如下:

2.MAX函数

1.用途:

求非空的最大值。

2.案例演示:

(1)查询10和20部门中,月收入最高的员工?

SELECT SUM(sal),MAX(sal+IFNULL(comm,0))        # MAX求最大值
FROM t_emp 
WHERE deptno IN(10,20);

结果如下:

(2)查询员工名字最长的是几个字符?

SELECT MAX(LENGTH(ename))        # 与LENGTH()函数,打个配合
FROM t_emp;

结果如下:

3.MIN函数

与MAX函数正好相反。

1.用途:

求非空值的最小值

2.案例演示:

(1)求员工表中,员工编号最小的编号是?

SELECT MIN(empno)
FROM t_emp;

结果如下:

(2)求员工表中,雇佣日期最早的日期是?

SELECT MIN(hiredate)
FROM t_emp;

结果如下:

5.AVG函数

1.用途

求非空值的平均值。

对象只能是数字型。非0数字的平均值为0

2.案例演示

求员工表中的员工工资的平均值?

SELECT AVG(sal+IFNULL(comm,0)) AS avg        # 用AS给起个别名
FROM t_emp;

结果如下:

6.COUNT函数

1.用途:

求记录的数量。

有两种写法:

  • COUNT(*)-------------求记录的数量,全部都有
  • COUNT(comm)------求记录的数量,只统计非空值的记录

2.案例演示:

求员工表中,总的记录数,和有佣金的记录数?

SELECT
    COUNT(*),COUNT(comm)
FROM t_emp;

结果如下:

2.3 练习

1.查询10和20部门中,底薪超过2000元并且工龄超过15年的员工人数?

分析:有3个条件:部门、底薪、工龄

SELECT
    COUNT(*)
FROM t_emp
WHERE deptno IN(10,20) AND sal>=2000 AND DATEDIFF(NOW(),hiredate)/365>=15;

结果如下:

2.查询1985年以后入职的员工,底薪超过公司平均底薪的员工数量?

是不是什么条件,都可以写进WHERE子句中?

不是,汇总函数永远不能放进WHERE子句中。

因为汇总函数执行的前提是,必须先划定清晰的数据范围。

同时,WHERE子句的核心使命就是根据给定条件,限定数据范围。

所以,汇总函数只能放在WHERE子句之后。

即,上述的五大汇总函数,只能放在SELECT子句中。

SELECT
    COUNT(*)
FROM t_emp
WHERE hiredate>="1985-01-01" AND sal>AVG(sal);        # ❌

结果如下:

三、分组查询

上节讲的是汇总函数,默认统计的是全表范围的数据,配合WHERE子句,可以缩小统计的范围。

但是,并不总能满足日常开发需求。因为很多时候,需要对数据进行分组之后,才进行汇总统计。

3.1 GROUP BY子句

通过一定规则,将数据集划分成若干小区域,然后对每个小区域使用五大汇总函数进行汇总处理。

SELECT
    deptno,ROUND(AVG(sal))        # 再使用五大汇总函数,汇总处理
FROM t_emp
GROUP BY deptno;            # 先按照部门编号分组

结果如下:

3.2 逐级分组

上面的只是一级分组,根据实际情况,也可以进行二级分组。

1.案例分析:

查询每个部门里,每种职位的人员数量和平均底薪?

一级分组:按照部门先分组

二级分组:按照职位再分组

SELECT
    deptno,job,COUNT(*),AVG(sal)
FROM t_emp
GROUP BY deptno,job
ORDER BY deptno;

结果如下:

3.3 GROUP BY子句对SELECT子句的规定

若查询语句中有GROUP BY子句,那么SELECT子句中的内容就必须遵守规定:

SELECT子句只可以包含汇总函数,或只可以包含GROUP BY子句的分组列。

之所以有上述规定,是因为为了保持数据的匹配性。

3.4 功能:对分组的结果集再次做汇总计算

上面的是对分组后的数据,进行汇总处理;接下来,是对前面得到的数据结果集,进一步进行二次汇总处理。

WITH ROLLUP

3.5 GROUP_CONCAT函数:非分组字段合并成一条记录

1.用途:

可以把分组查询中的多个非分组字段合并成一条记录

2.案例应用:

查询每个部门中底薪超过2000元的人数和员工姓名?

SELECT deptno,COUNT(*),GROUP_CONCAT(ename)        # 此处员工姓名就是非分组字段
FROM t_emp
WHERE sal>=2000
GROUP BY deptno;

注:这里的CONCAT是“连接”的意思

3.6 子句的执行顺序

FROM--->WHERE--->GROUP BY--->SELECT--->ORDER BY--->LIMIT

GROUP BY应该紧缩WHERE其后,只有根据条件WHERE缩小了范围后,再分组分析。

四、HAVING 子句

4.1 必要性

1.常见问题

因为有些条件查询,用GROUP BY子句并不是总能满足实际开发需求。

SELECT deptno
FROM t_emp
WHERE AVG(sal)>=2000
GROUP BY deptno;

--->
❌

上述问题出现在,在WHERE子句中,出现了汇总函数。两者的定位相互矛盾。

此时,为了装得下包含汇总函数的条件,HAVING子句,应运而生。

2.解决办法

将包含汇总函数的条件,通过HAVING关键字,放在GROUP BY子句中。

SELECT deptno
FROM t_emp 
GROUP BY deptno HAVING AVG(sal)>=2000;    # 先分好组,再用汇总函数计算平均值

4.2 特点

(1)HAVING子句跟WHERE子句功能相同,都是用来条件筛选。但是,因为存在汇总函数以及执行顺序的原因,HAVING子句就必须依赖GROUP BY子句,不能单独存在。

(2)HAVING子句中,拿汇总函数跟具体的数据进行条件判断是可以的,但是,拿汇总函数跟某个字段进行条件判断,就不行了。(只能用表连接)

4.3 案例应用

查询每个部门中,1982年以后入职的员工超过2个人的部门编号?

SELECT deptno
FROM t_emp 
WHERE hiredate>="1982-01-01"
GROUP BY deptno HAVING COUNT(*)>=2;            # 将包含汇总函数的条件,放在GROUP BY子句中

4. 4 简化写法

(1)在GROUP BY子句中,用1代替SELECT子句中第一列进行分组

  • 正常写法:
SELECT deptno,COUNT(*)
FROM t_emp 
GROUP BY deptno;

  • 简化写法:
SELECT deptno,COUNT(*)
FROM t_emp 
GROUP BY 1;        # 这里的1代表SELECT子句中第一列:deptno

(2)

WHERE子句是不能被HAVING子句替代的,虽然表面上两者功能上略有相同,但是,两者的实质定位、执行顺序是有差异的。

  • 虽然语法不报错、结果也对,但是不没意义的写法:
SELECT deptno,COUNT(*)
FROM t_emp 
GROUP BY 1 HAVING deptno IN(10,20);
  • 推荐的正确的写法:
SELECT deptno,COUNT(*)
FROM t_emp 
WHERE deptno IN(10,20)        # 普通的条件查询,让WHERE打冲锋
GROUP BY 1;

五、多张表连接查询

上面讲的是从一张表中来分析数据,接下来学习从多张表中来分析数据。这也更符合实际的开发场景。

比如,一个逻辑库中有上百张数据表,一个查询语句经常会查询七八张数据表,甚至十几张数据表。工作必备技能。

下面的操作,都是在FROM子句中。

5.1 指定连接条件

1.语法

从多张表中提取数据,必须指定关联的条件。如果没有关联条件,就会出现无条件连接,两张表的数据就会交叉连接,产生笛卡尔积。这不符合现实逻辑。

(1)没有关联条件的多张表连接:

只有JOIN

(2)指定关联条件的多张表连接:

JOIN-ON

ON的作用是,当后面写的条件满足时,两个表才连接成功。“合体”生成一整张临时表。

2.案例应用

SELECT e.empno,e.ename,d.dname                        # 查询的是两张表
FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno;

5.2 表连接的分类

分两种:内连接、外连接

  • 内连接:结果集里,只保留符合连接条件的记录
  • 外连接:不管符不符合连接条件,记录都保留在结果集里

5.3 内连接

1.特点

  • 结果集里,只保留符合连接条件的记录
  • 最常见的一种表连接。用于查询多张数据表同时符合的记录:

2.多种语法形式

(1)标准写法1:

(2)其他写法2:

将上面的连接条件,放到WHERE子句中:

(3)其他写法3:

在写法2的基础上,去掉JOIN关键字,用逗号将表名分开:

3.案例演示

(1)标准写法1:

SELECT e.empno,e.ename,d.dname        # 查询的是两张表
FROM t_emp e JOIN t_dept d 
ON e.deptno=d.deptno;

(2)其他写法2:

SELECT e.empno,e.ename,d.dname        # 查询的是两张表
FROM t_emp e JOIN t_dept d 
WHERE e.deptno=d.deptno;

(3)其他写法3:

SELECT e.empno,e.ename,d.dname        # 查询的是两张表
FROM t_emp e,t_dept d 
WHERE e.deptno=d.deptno;

多张表的连接查询很重要,后续工作会经常使用,接下来做一些例题,以巩固语法。

4.课堂例题1:查询每个员工的工号、姓名、部门名称、底薪、职位、工资等级?

分析:

  • 涉及三张表:员工表、部门表、工资等级表。
  • 员工表与部门表有相同的字段,但是员工表与工资表没有相同字段,不过有逻辑关系的字段
SELECT 
    e.empno,e.ename,d.dname,e.sal,e.job,s.grade
FROM t_emp e 
    JOIN t_dept d ON e.deptno=d.deptno                          # 员工表与部门表,有相同的字段
    JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal;      # 员工表与工资表,没有相同字段,不过有逻辑关系的字段

小结:内连接的两张数据表,不一定必须有同名字段,只要字段之间符合逻辑关系就可以。

5.课堂例题2:查询与SCOTT相同部门的员工都有谁?

(1)先查一下该员工所处的部门是哪个:

SELECT 
    deptno
FROM t_emp 
WHERE ename="SCOTT";

(2)把上面的SQL语句括起来,把上面的结果作为条件,放在WHERE子句中进行筛选:

SELECT ename
FROM t_emp
WHERE deptno=
    (SELECT deptno FROM t_emp WHERE ename="SCOTT");

(3)上面的结果集里,有SCOTT,这是不合理的。应该去掉他,改为:

SELECT ename
FROM t_emp
WHERE deptno=
    (SELECT deptno FROM t_emp WHERE ename="SCOTT")
    AND ename!="SCOTT";            # 剔除掉自己

这个写法是子查询,这很符合我们的思考习惯,但是,数据库执行的效率是很低的。

因为,每运行一条员工表中的记录,都要去重新运行一遍WHERE子句中的deptno=(SELECT deptno FROM t_emp WHERE ename="SCOTT")

员工表中有1000条记录,WHERE子句及内容,就要运行1000遍。

(4)改造后的正确写法:

SELECT
    e2.ename
FROM t_emp e1 JOIN t_emp e2 ON e1.deptno=e2.deptno        #因为一张表与它的“分身”,是完全相同的,也就一定会有同名字段
WHERE e1.ename="SCOTT" AND e2.ename!="SCOTT";

小结:相同的数据表也可以做表连接。

还是没有明白?尤其是WHERE子句中的条件

5.4 巩固练习

1.练习1.查询底薪超过公司平均底薪的员工信息?

分析:

  • 两个不知道:公司平均底薪是多少?谁超过了这个值?
  • 用表连接做:

写法1:

看似正常的SQL语句,为什么是语法错误的呢?

SELECT e2.empno,e2.ename,e2.sal
FROM t_emp e1 JOIN t_emp e2 ON e2.sal>=AVG(e1.sal);        #自己与自己做表连接是可以的,但是“娇生惯养”的汇总函数这样出现,就不合理

上面的ON的功能同WHERE子句。所以,就恍然大悟:WHERE子句中不能有汇总函数!

ON同理,连接条件中出现汇总函数,也是错误的。

因为,汇总函数就只能在WHERE子句之后,就更不应该放进FROM子句中了。

写法2:

(1)先求出公司的平均底薪:

SELECT
    AVG(sal)        # 汇总函数,的结果是一条记录
FROM t_emp;

(2)将上面查询后的结果集视为一张新的表,写在FROM子句中,通过JOIN-ON,与原表做表连接:

SELECT e.empno,e.ename,e.sal
FROM t_emp e 
    JOIN (SELECT AVG(sal) avg FROM t_emp) t ON e.sal>=t.avg;    # 把汇总函数及其范围包裹起来,其结果通过列别名形式见天日

小结:数据集也可以作为一张“表”,来跟其他表进行连接

2.练习2.查询RESEARCH部门的人数、最高底薪、最低底薪、平均底薪、平均工龄?

SELECT 
    COUNT(*),MAX(e.sal),MIN(e.sal),AVG(e.sal),FLOOR(AVG(DATEDIFF(NOW(),e.hiredate)/365))
FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno
WHERE d.dname="RESEARCH";

拓展:

工龄是不能四舍五入的。应该往下舍位。

SELECT FLOOR(28.9);        # 强制往下舍位        地板
SELECT CEIL(1.1);        # 强制往上进位        天花板

--->
28
2

3.练习3.查询每种职业的最高工资、最低工资、平均工资、最高工资等级、最低工资等级?

分析:员工表、工资等级表

SELECT e.job,
    MAX(e.sal+IFNULL(e.comm,0)),
    MIN(e.sal+IFNULL(e.comm,0)),
    AVG(e.sal+IFNULL(e.comm,0)),
    MAX(s.grade),
    MIN(s.grade)
FROM t_emp e 
    JOIN t_salgrade s ON (e.sal+IFNULL(e.comm,0)) BETWEEN s.losal AND s.hisal
GROUP BY e.job;

5.5 外连接

1.必要性

使用内连接,有时候会漏掉信息:

  • 因为内连接只会显示符合条件的记录,而外连接不管符不符合连接条件,记录都保留在结果集里
  • 查询条件是两个表的部门编号是相同的,但是陈浩没有部门编号。

2.语法

LEFT JOIN

必须保留左表所有的记录,然后跟右表去连接。如果右表有符合连接条件的记录,那么正常连接;如果右表没有符合连接条件的记录,右表就出一个NULL值跟左表连接。

(1)漏掉陈浩的内连接的写法:

SELECT e.empno,e.ename,d.dname
FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno;

(2)包含陈浩的外连接的写法:

SELECT e.empno,e.ename,d.dname
FROM t_emp e LEFT JOIN t_dept d ON e.deptno=d.deptno;        # 外连接

3.右外连接

最常用的是上面的外连接,即左外连接。其实,还有一种连接叫右外连接,差不多:

  • 因为是右外连接,所以全部保留的是右边的表。
SELECT e.empno,e.ename,d.dname
FROM t_dept d RIGHT JOIN t_emp e ON e.deptno=d.deptno;        # 要把全部保留的员工表放在右边

5.6 巩固练习

1.查询每个部门的名称和部门的人数是?

特殊之处在于:部门表中有个部门叫40部门,但是,员工表中没有一个员工是40部门的。

因此,表连接操作时,就必须保留部门表的40部门。

外连接,当仁不让。

(1)错误写法

SELECT d.dname,COUNT(*)
FROM t_dept d LEFT JOIN t_emp e ON d.deptno=e.deptno
GROUP BY d.deptno;

不是部门表中的40部门,没有人是这个部门的吗,怎么是1呢?

这是因为左外连接中,右边的表的字段如果没有记录,就用NULL代替,NULL也是一条记录。

(2)正确写法

SELECT d.dname,COUNT(e.deptno)        # 将员工表中的部门编号字段放进来
FROM t_dept d LEFT JOIN t_emp e ON d.deptno=e.deptno
GROUP BY d.deptno;                                

即,分组的时候,是用部门表的四个部门名;统计各部门的员工数量时,是用员工表的部门编号。

因为,前者刚好是4个部门名,后者是只有3个部门名的员工数量。

2.查询每个部门的名称和部门的人数?如果没有部门的员工,部门名称用NULL来代替显示。

(1)错误写法

SELECT d.dname,COUNT(e.deptno)        
FROM t_dept d 
    RIGHT JOIN t_emp e ON d.deptno=e.deptno        # 改为右连接
GROUP BY d.deptno;

(2)错误写法

(SELECT d.dname,COUNT(e.deptno)
FROM t_dept d 
     LEFT JOIN t_emp e ON d.deptno=e.deptno        # 左连接
GROUP BY d.deptno)
UNION                            # 用UNION关键字,进行查询语句的暴力连接
(SELECT d.dname,COUNT(e.deptno)
FROM t_dept d 
     RIGHT JOIN t_emp e ON d.deptno=e.deptno        # 右连接
GROUP BY d.deptno);

之所以这么显示,是因为陈浩是属于NULL部门的,右边的数字应该是1。

(3)正确写法

(SELECT d.dname,COUNT(e.deptno)
FROM t_dept d 
     LEFT JOIN t_emp e ON d.deptno=e.deptno        
GROUP BY d.deptno)
UNION                        
(SELECT d.dname,COUNT(*)            # 改为星号
FROM t_dept d 
     RIGHT JOIN t_emp e ON d.deptno=e.deptno        
GROUP BY d.deptno);

还是没有明白改为星号的区别?

3.查询每名员工的编号、姓名、部门名称、月薪、工资等级、工龄、上司编号、上司姓名、上司部门?

分析:员工表、部门表、工资等级表,上司的信息,用表连接去做

(1)我的写法:

SELECT e.empno,e.ename,d.dname,
    (sal+IFNULL(comm,0)),
    (SELECT s.grade FROM t_emp e JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal),
    FLOOR(DATEDIFF(NOW(),hiredate)/365),
    e.mgr
    ?            # 上司的编号、姓名、部门,咋整?
FROM t_emp e 
LEFT JOIN t_dept d ON e.deptno=d.deptno;


SELECT empno,mgr FROM t_emp        # ❌一个新表

SELECT e.ename
FROM t_emp e1 JOIN t_emp e2 ON e1.empno=e2.empno # ❌

(2)正确的写法:

SELECT e.empno,e.ename,d.dname,
    (e.sal+IFNULL(e.comm,0)),        # 注意1
    s.grade,                        # 注意2
    FLOOR(DATEDIFF(NOW(),hiredate)/365),
    t.empno AS mgrno,t.ename AS mname,t.dname AS mdname        # 注意3:上司的编号、姓名、部门
FROM t_emp e 
    LEFT JOIN t_dept d ON e.deptno=d.deptno
    LEFT JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal
    LEFT JOIN (SELECT e1.empno,e1.ename,d1.dname FROM t_emp e1 JOIN t_dept d1 ON e1.deptno=d1.deptno) t 
        ON e.mgr=t.empno;    
                                                # 关联条件:员工表的mgr与上司的结果集中的上司编号必须一致

最终结果:

其中的关键步骤是:

因为员工既是员工,又是别人的上司。所以,得出员工的编号、姓名、部门结果集,也是上司的编号、姓名、部门的结果集:

SELECT    e1.empno,e1.ename,d1.dname 
FROM t_emp e1 JOIN t_dept d1 ON e1.deptno=d1.deptno;

5.7 UNION关键字

UNION关键字:将多个查询语句的结果集进行合并。

使用要求:每个查询语句得到的结果集,其字段的个数、字段的名称,必须是相同的

5.8 ON子句和WHERE子句在外连接上的区别

在内连接上,ON子句和WHERE子句是没有区别的;

但是,在外连接上,两者有很大的区别。

1.查询10部门的员工编号、员工姓名、部门名称?

(1)用ON子句(还是在FROM子句中):

SELECT e.empno,e.ename,d.dname
FROM t_emp e 
    LEFT JOIN t_dept d ON e.deptno=d.deptno AND e.deptno=10;

发现了差错:有些不是10部门的员工,也被显示出来。

因为,用的是左外连接,即不管关联条件是否成立,左边的员工表的记录强制全部保留。

(2)用WHERE子句:

SELECT e.empno,e.ename,d.dname
FROM t_emp e 
    LEFT JOIN t_dept d ON e.deptno=d.deptno
WHERE e.deptno=10;        # 所以,一般的条件,还是让WHERE冲锋陷阵吧,使命就是缩小范围

成功显示了10部门的员工编号、员工姓名、部门名称,没有多余:

五、子查询

子查询确实效率低下,但也不是所有的子查询都不推荐。

5.1 概念

子查询是一种在查询中又嵌套另一个查询的语句。

子查询可以写在三个地方:SELECT子句、FROM子句、WHERE子句。其中,只推荐FROM子句中的子查询。

5.2 WHERE子句中的子查询

1.特点

最简单、最易理解,但是执行效率低。

2.WHERE子句中的子查询写法:

查询底薪超过公司平均底薪的员工的信息?

SELECT empno,ename,sal
FROM t_emp
WHERE sal>=(SELECT AVG(sal) FROM t_emp);

5.3 FROM子句中的子查询

前面其实已经用过了。

1.特点

只会执行1次,查询效率高。

本质还是因为,FROM子句中的所有成员,都是只执行一次的。

2.FROM子句中的子查询写法:

查询底薪超过公司的部门平均底薪的员工的信息?

(1)只子查询得到的结果集:

SELECT deptno,AVG(sal) AS avg
FROM t_emp
GROUP BY deptno

(2)将上述结果集作为一张“表”,加入到FROM子句中:

SELECT empno,ename,e.sal,t.avg
FROM t_emp e 
    JOIN (SELECT deptno,AVG(sal) AS avg FROM t_emp GROUP BY deptno) t
    ON e.deptno=t.deptno 
    AND e.sal>=t.avg;

5.4 SELECT子句中的子查询

1.特点

同WHERE子句中子查询,每输出一条记录,都要执行一次,查询效率很低。不推荐。

2.案例演示

SELECT
    e.empno,e.ename,
    (SELECT dname FROM t_dept WHERE deptno=e.deptno)
FROM t_emp e;

5.5 单行子查询、多行子查询

以子查询的结果集的数量,来划分子查询:

1.单行子查询

结果集只有1条记录。

2.多行子查询

结果集有多行记录。

只能出现在WHERE子句、FROM子句中。

3.案例应用

用子查询,查找FORD和MARTIN两个人的部门同事?

  • 名字是FORD和MARTIN的员工,所在的部门编号是多少:
SELECT deptno FROM t_emp WHERE ename IN("FORD","MARTIN");

  • 注意下运算符IN,逻辑上的或关系:

  • 正确的写法:
SELECT ename
FROM t_emp
WHERE
    deptno IN (SELECT deptno FROM t_emp WHERE ename IN("FORD","MARTIN")) # 相当于WHERE deptno IN (20,30)
    AND ename NOT IN ("FORD","MARTIN");        # IN运算符,真好使啊

六、WHERE子句中的多行子查询

当使用WHERE子句时,可以用以下关键字来处理多行表达式结果集的条件判断:

IN、ALL、ANY、EXISTS

6.1 ALL、ANY关键字

查询比FORD和MARTIN底薪都高的员工信息有谁?

因为结果集中,返回了多条记录。

  • 先查询出FORD和MARTIN的底薪:
SELECT sal FROM t_emp WHERE ename IN("FORD","MARTIN");

  • 将上述的结果集放进WHERE子句中
SELECT ename
FROM t_emp 
WHERE sal>=ALL(SELECT sal FROM t_emp WHERE ename IN("FORD","MARTIN")) #相当于WHERE sal>=ALL(1250,3000)
    AND ename NOT IN ("FORD","MARTIN");

6.2 EXISTS关键字

1.语法

把原来在子查询之外的条件判断,写到子查询里面:

只要子查询的结果集不为空,就代表条件符合了;如果为空,就代表条件不符合。

2.案例应用

查询工资等级是3级或者4级的员工信息?

SELECT empno,ename,sal
FROM t_emp 
WHERE EXISTS(
        SELECT * FROM t_salgrade WHERE sal BETWEEN losal AND hisal AND grade IN (3,4)
);

七、总结

声明:Jerry's Blog|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 8.4 数据库的高级查询


Follow excellence, and success will chase you.