子查询

数据库技术学习 https://www.itkc8.com

子查询一(WHERE中的子查询)

子查询

子查询就是指的在一个完整的查询语句之中,嵌套若干个不同功能的小查询,从而一起完成复杂查询的一种编写形式,为了让读者更加清楚子查询的概念。

子查询返回结果
子查询可以返回的数据类型一共分为四种:

    1. 单行单列:返回的是一个具体列的内容,可以理解为一个单值数据;
    2. 单行多列:返回一行数据中多个列的内容;
    3. 多行单列:返回多行记录之中同一列的内容,相当于给出了一个操作范围;
    4. 多行多列:查询返回的结果是一张临时表;

在WHERE子句中使用子查询

在WHERE子句之中处理单行单列子查询、多行单列子查询、单行多列子查询。

单行单列子查询

 示例一、查询公司之中工资最低的雇员的完整信息

--查询公司之中工资最低的雇员的完整信息
SELECT * 
FROM emp e
WHERE e.sal=(
  SELECT MIN(sal) 
  FROM emp);

示例二、查询出基本工资比ALLEN低的全部雇员信息

复制代码

-- 查询出基本工资比ALLEN低的全部雇员信息
SELECT * 
FROM emp e
WHERE e.sal<(
 SELECT sal 
 FROM emp 
 WHERE ename='ALLEN'
);

复制代码

示例三、查询基本工资高于公司平均薪金的全部雇员信息

 

--查询基本工资高于公司平均薪金的全部雇员信息
SELECT *
FROM emp e
WHERE e.sal>(
SELECT AVG(sal)
FROM emp);

单行多列子查询。

示例四、查找出与ALLEN从事同一工作,并且基本工资高于雇员编号为7521的全部雇员信息,

复制代码

--查找出与ALLEN从事同一工作,并且基本工资高于雇员编号为7521的全部雇员信息,
SELECT *
FROM emp e
WHERE e.job=(
  SELECT job
  FROM emp 
  WHERE ename='ALLEN') 
  AND e.sal>(
  SELECT sal
  FROM emp 
  WHERE empno=7521);

复制代码

示例五、查询与SCOTT从事同一工作且工资相同的雇员信息

复制代码

SELECT *
FROM emp e
WHERE (e.job,e.sal) = (
  SELECT job,sal
  FROM emp 
  WHERE ename='SCOTT')
  AND ename<>'SCOTT';

复制代码

示例六、查询与雇员7566从事同一工作且领导相同的全部雇员信息

复制代码

  --查询与雇员7566从事同一工作且领导相同的全部雇员信息
SELECT *
FROM emp e
WHERE (e.job,e.mgr) =(
        SELECT job,mgr
        FROM emp
      WHERE empno=7566
);

复制代码

示例七、查询与ALLEN从事同一工作且在同一年雇佣的全部雇员信息(包括ALLEN)

复制代码

--查询与ALLEN从事同一工作且在同一年雇佣的全部雇员信息(包括ALLEN)
SELECT *
FROM emp e
WHERE (e.job,to_char(e.hiredate,'yyyy'))=(
           SELECT job,to_char(hiredate,'YYYY')
            FROM emp
            WHERE ename='ALLEN'
);

复制代码

多行单列子查询

 

主要使用三种操作符:IN、ANY、ALL

 IN操作

示例八、查询出与每个部门中最低工资相同的全部雇员信息

复制代码

--查询出与每个部门中最低工资相同的全部雇员信息
SELECT *
FROM emp e
WHERE e.sal IN(
     SELECT MIN(sal)
    FROM emp
    GROUP BY deptno
);

复制代码

示例九、查询出不与每个部门中最低工资相同的全部雇员信息

复制代码

--查询出不与每个部门中最低工资相同的全部雇员信息
SELECT *
FROM emp e
WHERE e.sal NOT IN(
     SELECT MIN(sal)
    FROM emp
    GROUP BY deptno
);

复制代码

ANY在使用中有如下三种使用形式:
=ANY:表示与子查询中的每个元素进行比较,功能与IN类似(然而<>ANY不等价于NOT IN)
>ANY:比子查询中返回结果的最小的要大(还包含了>=ANY)
<ANY:比子查询中返回结果的最大的要小(还包含了<=ANY)

示例十、查询出每个部门经理的工资

复制代码

--查询出每个部门经理的工资

SELECT  * 
FROM emp 
WHERE sal = ANY (
   SELECT MIN (sal)
  FROM emp
  WHERE job='MANAGER'
  GROUP BY deptno
);

复制代码

示例十一、查询出每个部门大于经理的工资

复制代码

--查询出每个部门大于经理的工资
SELECT  * 
FROM emp 
WHERE sal > ANY (
   SELECT MIN (sal)
  FROM emp
  WHERE job='MANAGER'
  GROUP BY deptno
);

复制代码

示例十二、查询出每个部门小于经理的工资

复制代码

--查询出每个部门小于经理的工资
SELECT  * 
FROM emp 
WHERE sal < ANY (
   SELECT MIN (sal)
  FROM emp
  WHERE job='MANAGER'
  GROUP BY deptno
);

复制代码

ALL操作符有以下三种用法:
<>ALL:等价于NOT IN(但是=ALL并不等价于IN)
>ALL:比子查询中最大的值还要大(还包含了>=ALL)
<ALL:比子查询中最小的值还要小(还包含了<=ALL)

示例十三、查询出每个部门不等于经理的工资

复制代码

--查询出每个部门不等于经理的工资
SELECT  * 
FROM emp 
WHERE sal <> ALL (
   SELECT MIN (sal)
  FROM emp
  WHERE job='MANAGER'
  GROUP BY deptno
);

复制代码

示例十四、

复制代码

SELECT  * 
FROM emp 
WHERE sal < ALL (
   SELECT MIN (sal)
  FROM emp
  WHERE job='MANAGER'
  GROUP BY deptno
);

复制代码

示例十五、

复制代码

SELECT  * 
FROM emp 
WHERE sal >ALL (
   SELECT MIN (sal)
  FROM emp
  WHERE job='MANAGER'
  GROUP BY deptno
);

复制代码

空数据判断

在SQL之中提供了一个exists结构用于判断子查询是否有数据返回。如果子查询中有数据返回,则exists结构返回true,反之返回false。

示例十五、验证exists结构

 

--验证exists结构
SELECT * FROM emp
    WHERE EXISTS(   --返回空值,没有内容输出
      SELECT * FROM emp WHERE empno=9999); --没有这个编号的员工

示例十六、

 SELECT * FROM emp
 WHERE EXISTS(SELECT * FROM emp);--有内容将返回数据

示例十七、

  SELECT * FROM emp
 WHERE NOT EXISTS(SELECT * FROM emp);--有数据,但取返,没有内容输出

 

 

 

 

HAVING子句的主要功能是对分组后的数据进行过滤,如果子查询在HAVING中表示要进行分组过滤,一般返回单行单列的数据

示例一、查询部门编号,人数,平均工资,并且要求这些部门的平均工资高于公司的平均工资

复制代码

 --查询部门编号,人数,平均工资,并且要求这些部门的平均工资高于公司的平均工资
 SELECT e.deptno,COUNT(e.empno),ROUND(AVG(e.sal),2)
 FROM emp e
 GROUP BY e.deptno
 HAVING AVG(e.sal)>(
        SELECT AVG(sal)
        FROM emp
 );
 

复制代码

示例二、查询出部门平均工资高的部门名称和平均工资

复制代码

 --查询出部门平均工资高的部门名称和平均工资
SELECT d.deptno,d.dname,AVG(e.sal) avgsal
FROM emp e,dept d
WHERE e.deptno=d.deptno
GROUP BY d.deptno,d.dname
HAVING AVG(e.sal)=(
    SELECT MAX(AVG(sal))
     FROM emp
     GROUP BY deptno
);

复制代码

 

FROM子句中使用子查询一般都是返回多行多列,可以将其当作一张数据表

 

示例一、查询出每个部门的编号,名称,位置,部门人数,平均工资

SELECT d.deptno,d.dname,d.loc,temp.con,temp.avgsal
FROM dept d,(SELECT deptno dno,COUNT(empno) con,ROUND (AVG(sal),2) avgsal
             FROM emp 
             GROUP BY deptno) temp
WHERE d.deptno=temp.dno;

 

示例二、查询出所有在部门SALES(销售部)工作的员工编号,姓名,基本工资,奖金,职位,入职日期,部门最高和最低工资

复制代码

SELECT e.empno,e.ename,e.sal,e.comm,e.job,e.hiredate,e.deptno,temp.maxsal,temp.minsal
FROM emp e,(
            SELECT deptno dno,MAX(sal) maxsal,MIN(sal) minsal
            FROM emp
            GROUP BY deptno
            ) temp
WHERE e.deptno=(SELECT deptno
                 FROM dept
                 WHERE dname='SALES')
                 AND e.deptno=temp.dno;

复制代码

 

示例三、查询出所有工资高于公司平均工资的员工编号,姓名,基本工资,职位,入职日期,部门名称,位置,上级领导姓名,公司的工资等级,部门人数,平均工资,平均服务年限

复制代码

SELECT e.empno,e.ename,e.job,e.hiredate,d.dname,d.loc,m.ename,s.grade,temp.avgsal,temp.avgyear
FROM emp e,dept d,emp m,salgrade s,(
                                   SELECT deptno dno,COUNT(empno) con,ROUND (AVG(sal),2) avgsal,ROUND(AVG(months_between(SYSDATE,hiredate)/12),2) avgyear
                                   FROM emp
                                   GROUP BY deptno
                                   ) temp
WHERE e.sal>(SELECT AVG(sal)
              FROM emp)
              AND e.deptno=d.deptno
              AND e.mgr=m.empno(+)
              AND e.sal BETWEEN s.losal AND s.hisal
              AND e.deptno=temp.dno;

复制代码

 

示例四、列出工资比ALLEN或者CLARK多的所有员工的编号,姓名,基本工资,部门名称,领导姓名,部门人数

复制代码

SELECT e.empno,e.ename,e.sal,d.dname,m.ename,temp.con
FROM emp e,dept d,emp m,(
                          SELECT deptno dno,COUNT(empno) con
                          FROM emp
                          GROUP BY deptno
                          )temp
WHERE e.sal>ANY(SELECT sal
                 FROM emp
                 WHERE ename IN('ALLEN','CLARK')
                 )
              AND e.ename NOT IN ('ALLEN','CLARK')
              AND e.deptno=d.deptno
              AND e.mgr=m.empno(+)
              AND e.deptno=temp.dno;

复制代码

 

示例五、列出公司各个部门的经理(一个部门只有一个)的姓名,工资,部门名称,部门人数,部门平均工资

 

复制代码

--列出公司各个部门的经理(一个部门只有一个)的姓名,工资,部门名称,部门人数,部门平均工资
SELECT e.ename,e.sal,d.dname,temp.con,temp.avgsal
FROM emp e,dept d,( 
                   SELECT deptno dno,COUNT(empno) con,ROUND(AVG(sal),2) avgsal
                   FROM emp
                   GROUP BY deptno
                   )temp
WHERE e.job='MANAGER'
       AND e.deptno=d.deptno(+)
       AND e.deptno=temp.dno;

复制代码

 

示例一、查询出每个部门的编号,名称,位置,部门人数,平均工资

SELECT d.deptno,d.dname,d.loc,
  (SELECT  COUNT(empno) FROM emp WHERE emp.deptno=d.deptno GROUP BY deptno) con,
  (SELECT AVG(sal) FROM emp WHERE emp.deptno=d.deptno GROUP BY deptno) avgsal
FROM dept d

WITH 子句

示例二、使用with子句将emp表中的数据定义为临时表

WITH e AS(
SELECT * FROM emp)
SELECT * FROM e;

示例三、查询每个部门的编号,名称,位置,部门平均工资,人数

复制代码

--查询每个部门的编号,名称,位置,部门平均工资,人数
WITH e AS(
  SELECT deptno dno,ROUND(AVG(sal),2) avgsal,COUNT(empno) con
  FROM emp
  GROUP BY deptno
)
SELECT d.deptno,d.dname,d.loc,e.avgsal,e.con
FROM dept d,e
WHERE d.deptno=e.dno(+);

复制代码

示例四、查询每个部门工资最高的员工编号,姓名,职位,入职日期,工资,部门编号,部门名称,显示结果按部门编号进行排序

复制代码

WITH e AS(
   SELECT deptno dno,MAX(sal) maxsal
   FROM emp
   GROUP BY deptno
)
SELECT em.ename,em.job,em.hiredate,em.sal,d.deptno,d.dname
FROM emp em,dept d,e
WHERE em.deptno=e.dno
       AND em.sal=e.maxsal
       AND d.deptno=e.dno
       ORDER BY em.deptno;

复制代码

数据库技术学习 https://www.itkc8.com

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值