SQL语言基础(高级查询)

1-1 集合查询

操作符

返回结果集

内容

UNION

由每个查询选择的所有不重复的行

并集。不包含重复值,默认按第 1 个查询的第 1 列升序排列

UNION ALL

由每个查询选择的所有的行,包括所有重复的行

包括所有重复的行,完全并集包含重复值,不排序

INTERSECT

由每个查询选择的所有不重复的相交行

交集。不包含重复行,按第 1 个查询的第 1 列升序排列

MINUS

在第一个查询中,不在后面查询中的行

不包含重复行,按第 1 个查询的第 1 列升序排列

UNION ALL 之外,系统会自动将重复的记录删除

系统将第一个查询的列名显示在输出中

UNION ALL 之外,系统自动按照第一个查询中的第一个列的升序排列

1-1-1  UNION 操作符

SELECT employee_id, job_id
FROM   employees
UNION
SELECT employee_id, job_id
FROM   job_history;

1-1-2  UNION ALL 操作符

UNION ALL 操作符返回两个查询的结果集的并集以及两个结果集的重复部分(不去重复值)

SELECT employee_id, job_id, department_id
FROM   employees
UNION ALL
SELECT employee_id, job_id, department_id
FROM   job_history

1-1-3  INTERSECT 操作符

INTERSECT 操作符返回两个结果集的交集

SELECT employee_id, job_id
FROM   employees
INTERSECT
SELECT employee_id, job_id
FROM   job_history;

1-1-4  MINUS 操作符

SELECT employee_id,job_id
FROM   employees
MINUS
SELECT employee_id,job_id
FROM   job_history;

使用集合的注意事项:

SELECT 列表中的列名和表达式在数量和数据类型上要相对应

括号可以改变执行的顺序

ORDER BY 子句:

只能在语句的最后出现

可以使用第一个查询中的列名, 别名或相对位置


1-2 分级查询

SELECT [LEVEL], column, expr...
FROM   table
[WHERE condition(s)]
[START WITH condition(s)]
[CONNECT BY PRIOR condition(s)] ;

1. 其中level 关键字是可选的,表示等级。

2.From 之后可以是table,view 但是只能是一个table

3.Where 条件限制了查询返回的行,但是不影响层次关系,不满足条件的节点不返回,但是这个不满足条件的节点的下层child 不受影响。

4.Start with 是表示开始节点,对于一个真实的层次关系,必须要有这个子句,但是不是必须的,后面详细介绍。

5.connect by prior 是指定父子关系,其中prior 的位置不一定要在connect by 之后,对于一个真实的层次关系,这也是必须的。

1-2-1 树形结构

 树结构的数据存放在表中,数据之间的层次关系即父子关系,通过表中的列与列间的关系来描述,如该表中的EMPLOYEE_ID MANAGER_ID EMPLOYEE_ID 表示该雇员的编号, MANAGER_ID 表示领导该雇员的人的编号,即子节点的MANAGER_ID 值等于父节点的EMPLOYEE_ID 值。在表的每一行中都有一个表示父节点的MANAGER_ID (除根节点外),通过每个节点的父节点,就可以确定整个树结构。

1-2-2 遍历树

   首先必须确定起始点,通过start with 子句,后面加条件,这个条件是任何合法的条件表达式。

    Start with 确定将哪行作为root ,如果没有start with, 则每行都当作root ,然后查找其后代,这不是一个真实的查询。Start with 后面可以使用子查询,如果有where 条件,则会截断层次中的相关满足条件的节点,但是不影响整个层次结构。可以带多个条件。

   运算符PRIOR 被放置于等号前后的位置,决定着查询时的检索顺序。

        PRIOR 被置于CONNECT BY 子句中等号的前面时,则强制从根节点到叶节点的顺序检索,即由父节点向子节点方向通过树结构,我们称之为自顶向下的方式。

        PIROR 运算符被置于CONNECT BY 子句中等号的后面时,则强制从叶节点到根节点的顺序检索,即由子节点向父节点方向通过树结构,我们称之为自底向上的方式。

CONNECT BY PRIOR column1 = column2



遍历树: 从底到顶

从底到顶查询树结构时 , 也要指定一个开始节点,以此开始向上查找其父节点,直至找到根节点,其结果将是结构树中的一枝数据

SELECT employee_id, last_name, job_id, manager_id
FROM   employees
START  WITH  employee_id = 101
CONNECT BY PRIOR manager_id = employee_id ;

遍历树: 从顶到底

  在自顶向下查询树结构时,不但可以从根节点开始,还可以定义任何节点为起始节点,以此开始向下查找。这样查找的结果就是以该节点为开始的结构树的一枝。

SELECT  last_name||' reports to '||
PRIOR   last_name "Walk Top Down"
FROM    employees
START   WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id ;

1-2-3  使用 LEVEL 伪列标记层次

在查询中,可以使用伪列LEVEL 显示每行数据的有关层次。LEVEL 将返回树型结构中当前节点的层次,可以使用LEVEL 来控制对树型结构进行遍历的深度。

在具有树结构的表中,每一行数据都是树结构中的一个节点,由于节点所处的层次位置不同,所以每行记录都可以有一个层号。层号根据节点与根节点的距离确定。不论从哪个节点开始,该起始根节点的层号始终为1 ,根节点的子节点为2 依此类推

使用 LEVEL LPAD 格式化分层查询

COLUMN org_chart FORMAT A12
SELECT level,
              LPAD(last_name, LENGTH(last_name)+(LEVEL*2)-2,‘-')
       AS org_chart
FROM   employees
START WITH last_name='King'
CONNECT BY PRIOR employee_id=manager_id

LEVEL  ORG_CHART

---                   -----------

1  King

2  - Kochhar

3  --Whalen

3  --Higgins

4  --- Gietz

2  -De Haan

3  -- Hunold

4  --- Emst

4  ---Lorentz

2  - Mourgos

3  -- Rajs

3  --Davies

3  --Matos

3  --Vargas

2  - Zlotkey

3  --Abel

3  --Taylor

3  --Gant

2  - Hartstein

3  --Fay

1-2-4 修剪分支

     where 子句会将节点删除,但是其后代不会受到影响

    connect by 中加上条件会将满足条件的整个树枝包括后代都删除

1-3  GROUP BY 子句的扩展

使用 ROLLUP 操作分组

使用 CUBE 操作分组

使用 GROUPING 函数处理 ROLLUP CUBE 操作所产生的空值

使用 GROUPING SETS 操作进行单独分组


1-3-1  带有 ROLLUP CUBE 操作的 GROUP BY 子句

使用带有ROLLUP CUBE 操作的GROUP BY 子句产生多种分组结果

ROLLUP 产生n + 1 种分组结果

CUBE 产生2 n 次方种分组结果


ROLLUP 操作符

SELECT  [column,] group_function(column). . .
FROM  table
[WHERE  condition]
[GROUP BY  [ROLLUP] group_by_expression]
[HAVING   having_expression];
[ORDER BY  column];

ROLLUP 是对 GROUP BY 子句的扩展

ROLLUP 产生n + 1 种分组结果,顺序是从右向左

SELECT   department_id, job_id, SUM(salary)
FROM     employees 
WHERE    department_id < 60
GROUP BY ROLLUP(department_id, job_id);

CUBE 操作符

SELECT  [column,] group_function(column)...
FROM  table
[WHERE  condition]
[GROUP BY  [CUBE] group_by_expression]
[HAVING   having_expression]
[ORDER BY  column];

CUBE 是对 GROUP BY 子句的扩展

CUBE 会产生类似于笛卡尔集的分组结果

SELECT   department_id, job_id, SUM(salary)
FROM     employees 
WHERE    department_id < 60
GROUP BY CUBE (department_id, job_id) ;


1-3-2  GROUPING 函数

SELECT    [column,] group_function(column) . ,
          GROUPING(expr)
FROM       table
[WHERE    condition]
[GROUP BY [ROLLUP][CUBE] group_by_expression]
[HAVING   having_expression]
[ORDER BY column];

GROUPING 函数可以和 CUBE ROLLUP 结合使用

使用 GROUPING 函数,可以找到哪些列在该行中参加了分组

使用 GROUPING 函数, 可以区分空值产生的原因

GROUPING 函数返回 0 1

SELECT   department_id DEPTID, job_id JOB,
         SUM(salary),
         GROUPING(department_id) GRP_DEPT,
         GROUPING(job_id) GRP_JOB
FROM     employees
WHERE    department_id < 50
GROUP BY ROLLUP(department_id, job_id);


1-3-3  GROUPING SETS

GROUPING SETS 是对GROUP BY 子句的进一步扩充

使用 GROUPING SETS 在同一个查询中定义多个分组集

Oracle GROUPING SETS 子句指定的分组集进行分组后用 UNION ALL 操作将各分组结果结合起来

Grouping set 的优点:

只进行一次分组即可

不必书写复杂的 UNION 语句

SELECT   department_id, job_id,
         manager_id,avg(salary)
FROM     employees
GROUP BY GROUPING SETS
((department_id,job_id), (job_id,manager_id));

1-3-4  复合列

复合列是被作为整体处理的一组列的集合

ROLLUP (a,b,c,d)

使用括号将若干列组成复合列在ROLLUP CUBE 中作为整体进行操作

ROLLUP CUBE , 复合列可以避免产生不必要的分组结果

SELECT   department_id, job_id, manager_id,
         SUM(salary)
FROM     employees 
GROUP BY ROLLUP( department_id,(job_id, manager_id));

1-3-5  连接分组集

连接分组集可以产生有用的对分组项的结合

将各分组集, ROLLUP CUBE 用逗号连接 Oracle 自动在 GROUP BY 子句中将各分组集进行连接

连接的结果是对各分组生成笛卡尔集

SELECT   department_id, job_id, manager_id,
         SUM(salary)
FROM     employees
GROUP BY department_id,
         ROLLUP(job_id),
         CUBE(manager_id);


请使用浏览器的分享功能分享到微信等