1 1 分析函数使用场景:
  2     1. 计算运行总量:逐一累加当前行与其之前行的每行记录数据。
  3     2. 查找当前行数据占总数据的百分比。
  4     3. 分区显示: 按照不同的部门或职位进行排列、统计。
  5     4. 计算流动数据行的平均值等
  6 
  7 
  8 2 分析函数的基本语法
  9 函数名称([参数,...])OVER(
 10     PARTITION BY 子句 字段,...
 11      [ORDER BY 子句 字段,...[ASC]DESC][NULLS FIRST|NULLS LAST]
 12      [WINDOWING 子句]);
 13      
 14 函数名称:类似于统计函数(COUNT(),SUM()函数等),或其他支持的函数。     
 15 OVER 子句: 为分析函数指明一个查询结果集,此语句在 SELECT 子句中使用。
 16 PARTITION BY 子句:将一个简单的结果集分为N组(或称为分区),而后按照不同的组对数据进行统计。
 17 ORDER BY 子句:明确指明数据在每组内的排列顺序,分析函数的结果与排列顺序有关 。 (NULLS FIRST|NULLS LAST: 表示返回数据行中包含 NULL 值时出现在排序序列前还是排序尾。)
 18 WINDOWING 子句(代名词):给定在定义变化的固定的数据窗口方法,分析函数将此数据进行操作。
 19 
 20 --在分析函数中,每一个分区(分组)称为一个窗口,每一个窗口都是当前行的计算范围。
 21 --分析函数中三中子句的组合顺序:
 221 种组合: 函数名称([参数,...]) OVER(PARTITION BY 子句,ORDER BY 子句,WINDOWING 子句)。
 232 种组合: 函数名称([参数,...]) OVER(PARTITION BY 子句,ORDER BY 子句)。
 243 种组合: 函数名称([参数,...]) OVER(PARTITION BY 子句)。
 254 种组合: 函数名称([参数,...]) OVER(ORDER BY 子句,WINDOWING 子句)。
 265 种组合: 函数名称([参数,...]) OVER(ORDER BY 子句)。
 276 种组合: 函数名称([参数,...]) OVER()。
 28 
 29 3 PARTITION BY 子句
 30     在分析函数中,最重要的概念就是数据进行分区,而后才可以利用分析函数针对每一分区的数据进行操作。如果在定义时没有使用分区,则表示全部的结果集作为一组。
 31 
 32 --用例 ,本例中 SUM 是一个分析函数。
 33 SELECT deptno,ename,sal,
 34        SUM(sal) OVER(PARTITION BY deptno) sum
 35 FROM emp;
 36 
 37 4 ORDER BY 子句
 38     ORDER BY 子句用于设置在每个分区内数据的排序结果,排序结果将直接影响分析函数的计算结果。
 39 
 40 --用例 
 41 SELECT deptno,ename,sal,hiredate
 42        RANK() OVER(PARTITION BY deptno ORDER BY sal,hiredate DESC) rk
 43 FROM emp;
 44 
 45 
 46 5 WINDOWING BY 子句
 47     分窗子句主要用于定义一个变化或固定的数据窗口方法,以及分析函数在操作的集合。有以下两种实现方法。
 48     1.实现一: 值域窗(RANGE WINDOW),逻辑偏移。当前分区中当前行的前N行到当前行的记录集。
 49     2.实现二: 行窗(ROWS WINDOW),物理偏移。以排序的结果顺序计算偏移当前行的起始记录集。
 50     
 51     如果要指定 RANGE 或 ROWS 的偏移量,可以采用如下几种排列:
 52     1. RANGE | ROWS 数字 PRECEDING。
 53     2. RANGE | ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 。 (默认方式)
 54     3. RANGE | ROWS BETWEEN CURRENT ROW  AND UNBOUNDED FOLLOWING 
 55     
 56     PRECEDING : 主要是设置一个偏移量,这个偏移量可以是用户设置的数字,或者是其他标记。
 57     BETWEEN ... AND : 设置一个偏移量的操作范围。
 58     UNBOUNDED PRECEDING: 不限制偏移量大小
 59     CURRENT ROW :表示当前行。
 60     FOLLOWING : 如果不写此语句,表示使用上 N行与当前行指定数据比较,如果编写此语句,表示当前行与下N行数据进行比较。
 61 
 62 5.1 RANGE 子句
 63     RANGE子句设置的是一个查询范围的偏移量,排序列的数值必须大于等于(或小于等于)"当前行列数值 +/- 偏移量" 的所有行。
 64 
 65 
 66 --设置 sal 上设置偏移量
 67 SELECT deptno,ename,sal,
 68     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal RANGE 300 PRECEDING AND 300 FOLLOWING) sum
 69 FROM emp;
 70 
 71 --设置偏移量为300,采用一下匹配的方式处理
 72 SELECT deptno,ename,sal,
 73     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal RANGE BETWEEN 0 PRECEDING AND 300 FOLLOWING) sum
 74 FROM emp;
 75 
 76 --匹配当前行数据 , CURRENT ROW 选项表示与当前行数据相同,所以只有相同的数据才会使用SUM()计算出总和。
 77 SELECT deptno,ename,sal,
 78     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal RANGE BETWEEN 0 PRECEDING AND CURRENT ROW) sum
 79 FROM emp;
 80 
 81 --使用 UNBOUNDED 不设置边界。
 82 SELECT deptno,ename,sal,
 83     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) sum
 84 FROM emp;    
 85 
 86 5.2  ROWS 子句:
 87     ROWS子句最大的功能是设置一个当前行的起始物理偏移量。
 88 
 89 --设置两行物理偏移    
 90 SELECT deptno,ename,sal,
 91     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal ROWS 2 PRECEDING ) sum
 92 FROM emp;    
 93 
 94 
 95 --设置查询行范围    
 96 SELECT deptno,ename,sal,
 97     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal ROWS BETWEEN UNBOUNDED  PRECEDING AND UNBOUNDED FOLLOWING) sum
 98 FROM emp;    
 99 
100 
101 6 分析函数范例
102 6.1 数据统计函数:
103     SUM(DISTINCT|ALL 表达式) :计算分区(分组)中的数据累加和。
104     MIN(DISTINCT|ALL 表达式) : 查找分区(分组)中的最小值。
105     MAX(DISTINCT|ALL 表达式) :查找分区(分组)中的最小值。
106     AVG(DISTINCT|ALL 表达式) :计算分区(分组)中的数据平均值。
107     COUNT(*|DISTINCT|ALL 表达式):计算分区(分组)中的数据量。
108 
109 --范例:
110 --范例一:
111 查询雇员编号是7639 的雇员姓名、职位、基本工资、部门编号、部门的人数、平均工资、最高工资、最低工资、总工资 。
112 SELECT * 
113 FROM (
114    SELECT empno,ename,job,sal,deptno,
115           COUNT(empno) OVER(PARTITION BY deptno)count,
116           ROUND(AVG(sal) OVER(PARTITION BY deptno)) avg,
117           SUM(sal) OVER(PARTITION BY deptno) sum,
118           MAX(sal) OVER(PARTITION BY deptno) max,
119           MIN(sal) OVER(PARTITION BY deptno) min
120       FROM emp ) temp
121 WHERE temp.empno=7369;
122 
123 --范例二:
124 查询每个雇员的编号、姓名、基本工资、所在部门的名称、部门位置,以及此部门的平均工资、最高工资和最低工资。(由于需要针对每一个部门找出整个部门的工资统计信息,所以可以利用分窗子句完成,而每个分窗子句的范围应该是所有数据,所以可以用“RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING” 作为范围限定。)
125 SELECT e.empno,e.ename,e.sal,d.dname,d.loc,
126    ROUND(AVG(sal) OVER(PARTITION BY e.deptno ORDER by sal RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) avg_salary,
127    MAX(sal) OVER(PARTITION BY e.deptno ORDER by sal RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) max_salary,
128    MIN(sal) OVER(PARTITION BY e.deptno ORDER by sal RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) min_salary
129 FROM emp e,dept d 
130 WHERE e.deptno=d.deptno;
131    
132 6.2 等级函数:
133     RANK():根据 ORDER BY 子句的排序字段,从分区(分组)查询每一行数据,按照排序生成序号,会出现相同序号。
134     DENSE_RANK():根据 ORDER BY 子句的排序字段,从分区(分组)查询每一行数据,按照排序生成序号,不会出现相同序号。
135     FIRST():取出 DENSE_RANK 返回集合中第一行数据。
136     LAST():取出 DENSE_RANK 返回集合中最后一行数据。
137     FIRST_VALUE(列):返回分区(分组)中的第一个值。
138     LAST_VALUE(列):返回分区(分组)中的最后一个值。
139     LAG(列名称[,行数字][,默认值]):访问分区(分组)中指定前N行的记录,如果没有则返回默认值。
140     LEAD(列名称[,行数字][,默认值]):访问分区(分组)中指定后N行的记录,如果没有则返回默认值。
141     ROW_NUMBER() :返回每组中的行号。
142 
143 --范例一 记录标记函数:RANK() 和 DENSE_RANK()
144 SELECT deptno,ename,sal,
145     RANK() OVER(PARTITION BY deptno ORDER BY sal) rank_result,
146     DENSE_RANK() OVER(PARTITION BY deptno ORDER BY sal) dense_rank_result
147 FROM emp;
148 
149 --范例二 行标记函数: ROW_NUMBER()
150 SELECT deptno,ename,sal,
151     ROW_NUMBER() OVER(PARTITION BY deptno ORDER BY sal) row_result_deptno,
152     ROW_NUMBER() OVER(ORDER BY sal) row_result_all
153 FROM emp;
154 
155 --范例三: 取出首行或尾行数据 DENSE_RANK
156 当用户使用了DENSE_RANK()函数进行数据排序后,可以利用FIRST取得返回结果集中的首行,或使用 LAST 取得返回结果集中的最后一行 。但必须使用 KEEP 语句完成。
157 KEEP 语句语法:
158              分组函数()
159              KEEP 
160              (DENSE_RANK FIRST|LAST ORDER BY 表达式 [ASC|DESC][NULLS [FIRST|LAST]],...)
161              [OVER() 分区查询]
162 
163 查询每个部门的最高及最低工资:
164 SELECT deptno
165     MAX(sal) KEEP(DENSE_RANK FIRST ORDER BY sal DESC) max_salary,
166     MIN(sal) KEEP(DENSE_RANK LAST ORDER BY sal DESC) min_salary
167 FROM emp
168 GROUP BY deptno;
169 
170 --范例四 取出首行或尾行记录:FIRST_VALUE(列) 和 LAST_VALUE(列) 
171 SELECT deptno,ename,sal,
172     FIRST_VALUE() OVER(PARTITION BY deptno ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) first_result,
173     LAST_VALUE()  OVER(PARTITION BY deptno ORDER BY sal RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) last_result
174 FROM emp
175 WHERE deptno=10 ;    
176 
177 
178 --范例五 比较相邻记录:
179 SELECT deptno,ename,sal,
180     LAG(sal,2,0) OVER(PARTITION BY deptno ORDER BY sal) lag_result,
181     LEAD(sal,2,0) OVER(PARTITION BY deptno ORDER BY sal) lead_result
182 FROM emp
183 WHERE deptno=20 ;
184 
185 
186 6.3 报表函数:
187     CUME_DIST() : 计算一行在分区(分组)中的相对位置
188     NTILE(数字):将一个分许(分组)分为 '表达式' 的散列表示。
189     RATIO_TO_REPORT(表达式): 该函数结算 expression/(sum(expression)) 的值,它给出相对于总数的百分比。
190     
191     
192 --范例一 : CUME_DIST()
193 SELECT deptno,ename,sal,
194     CUME_DIST OVER(PARTITION BY deptno ORDER BY sal) cume
195 FROM emp
196 WHERE deptno IN (10,20) ;
197 
198 --范例二 :NTILE(数字)
199 SELECT deptno,sal,
200     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal) sum_result,
201     NTILE(3) OVER(PARTITION BY deptno ORDER BY sal) ntile_result_a,
202     NTILE(6) OVER(PARTITION BY deptno ORDER BY sal) ntile_result_b
203 FROM emp
204 ;
205 
206 
207 --范例三 :
208 SELECT deptno,SUM(sal),
209     SUM(sal) OVER(PARTITION BY deptno ORDER BY sal) sum_result,
210     ROUND(RATIO_TO_REPORT(SUM(sal)) OVER(),5) rate,
211     ROUND(RATIO_TO_REPORT(SUM(sal)) OVER(),5)*100||'%' precent
212 FROM emp
213 ORDER BY deptno
214 ;
215 
216 
217 
218 
219 7 行列转换
220 用户在制作数据报表时,经常会使用到数据的行列转换操作。
221 
222 
223 7.1 DECODE
224 --范例一: 使用decode()
225 查询每个部门中各个职位的总工资。
226 SELECT deptno,
227     SUM(DECODE(job,'PRESIDENT',sal,0)) PRESIDENT_JOB,
228     SUM(DECODE(job,'MANAGER',sal,0)) MANAGER_JOB,
229     SUM(DECODE(job,'ANALYST',sal,0)) ANALYST_JOB,
230     SUM(DECODE(job,'CLERK',sal,0)) CLERK_JOB,
231     SUM(DECODE(job,'SALESMAN',sal,0)) SALESMAN_JOB
232 FROM emp
233 GROUP BY deptno;
234 
235 --范例二: 不使用decode(),使用子查询。
236 查询每个部门中各个职位的总工资。
237 SELECT temp.dno,SUM(PRESIDENT_JOB),SUM(MANAGER_JOB),SUM(ANALYST_JOB),SUM(CLERK_JOB),SUM(SALESMAN_JOB)
238 FROM (
239     SELECT deptno dno,
240         (SELECT SUM(sal) FROM emp WHERE job='PRESIDENT' AND empno=e.empno ) PRESIDENT_JOB,
241         (SELECT SUM(sal) FROM emp WHERE job='MANAGER' AND empno=e.empno ) MANAGER_JOB,
242         (SELECT SUM(sal) FROM emp WHERE job='ANALYST' AND empno=e.empno ) ANALYST_JOB,
243         (SELECT SUM(sal) FROM emp WHERE job='CLERK' AND empno=e.empno ) CLERK_JOB,
244         (SELECT SUM(sal) FROM emp WHERE job='SALESMAN' AND empno=e.empno ) SALESMAN_JOB
245     FROM emp e
246 ) temp
247 GROUP BY temp.dno
248 ORDER BY temp.dno DESC;
249 
250 7.2  11G以后 ,PIVOT() 和 UNPIVOT()
251 
252 7.2.1 PIVOT() :将行转换为列。
253 语法:
254     SELECT *|[别名] ...
255     FROM 子查询
256     PIVOT(
257         统计函数(列)s FOR 转换列名称 IN (
258             内容1 [[AS] 别名],
259             内容2 [[AS] 别名],
260               ...
261             内容n [[AS] 别名],
262         
263         )
264     )
265     [WHERE 条件(s)]     
266     [GROUP BY 分组字段1,分组字段2,... ]     
267     [HAVING 过滤条件(s) ]     
268     [ORDER BY 排序字段 ASC|DESC ];
269 
270 子查询:    此处规定了在PIVOT()函数操作过程中,所需要使用到的数据(设置子查询确定行和列)。
271 统计函数(列):在转换过程中,设置要进行统计的数据列及统计函数,可以设置多个统计函数。
272 FOR 转换列名称: 将子查询中返回的指定数据变为显示的列。
273 
274 --范例一: 使用PIVOT()
275 SELECT * FROM (SELECT deptno,job,sal FROM emp)
276 PIVOT(
277     SUM(sal)
278     FOR job IN (
279     'PRESIDENT' AS PRESIDENT_JOB,
280     'MANAGER' AS MANAGER_JOB,
281     'ANALYST' AS ANALYST_JOB,
282     'CLERK' AS CLERK_JOB,
283     'SALESMAN' AS SALESMAN_JOB
284     )
285 ) ORDER BY deptno;
286 
287 
288 --范例二: 使用PIVOT() 查询更多信息
289 SELECT * FROM (
290     SELECT job,deptno,sal,
291         SUM(sal) OVER(PARTITION BY deptno) sum_sal,
292         MAX(sal) OVER(PARTITION BY deptno) max_sal,
293         MIN(sal) OVER(PARTITION BY deptno) min_sal
294     FROM emp)
295 PIVOT(
296     SUM(sal)
297     FOR job IN(
298           'PRESIDENT' AS PRESIDENT_JOB,
299         'MANAGER' AS MANAGER_JOB,
300         'ANALYST' AS ANALYST_JOB,
301         'CLERK' AS CLERK_JOB,
302         'SALESMAN' AS SALESMAN_JOB  
303     )
304 ) ORDER by deptno;
305     
306 
307 
308 
309 --范例三:设置多个统计函数,查询每个部门不同职位的总工资,以及每个部门不同职位的最高工资。
310 SELECT * FROM (SELECT deptno,job,sal FROM emp)
311 PIVOT(
312     SUM(sal) AS sum_sal,MAX(sal) as sum_max
313     FOR job IN(
314           'PRESIDENT' AS PRESIDENT_JOB,
315         'MANAGER' AS MANAGER_JOB,
316         'ANALYST' AS ANALYST_JOB,
317         'CLERK' AS CLERK_JOB,
318         'SALESMAN' AS SALESMAN_JOB  
319     )
320 ) ORDER by deptno;
321 
322 --范例四 :输出为XML:
323 SELECT * FROM (SELECT deptno,job,sal FROM emp)
324 PIVOT XML(
325         SUM(sal)
326         FOR job IN (ANY)
327 )ORDER BY deptno;
328 
329 --范例五 :设置多个统计列,如果emp表中增加了一个性别sex,同时要针对不同职位的不同性别进行总工资的统计,可以在FOR 语句中设置多个列。
330 SELECT * FROM (SELECT deptno,job,sal,sex FROM emp)
331 PIVOT(
332     SUM(sal) AS sum_sal,MAX(sal) as sum_max
333     FOR(job,sex) IN(
334         ('MANAGER','') AS manager_male_job,
335         ('MANAGER','') AS manager_female_job,
336         ('CLERK','') AS CLERK_male_job,
337         ('CLERK','') AS CLERK_female_job
338     )
339 ) ORDER BY deptno;
340 
341 7.2.2 UNPIVOT() 函数 : 将列重新转换为行。
342 语法:
343     SELECT *|[别名] ...
344     FROM 子查询
345     UNPIVOT [INCLUDE NULLS|EXCLUDE NULLS](
346         统计函数(列)s FOR 转换列名称 IN (
347             内容1 [[AS] 别名],
348             内容2 [[AS] 别名],
349               ...
350             内容n [[AS] 别名],
351         
352         )
353     )
354     [WHERE 条件(s)]     
355     [GROUP BY 分组字段1,分组字段2,... ]     
356     [HAVING 过滤条件(s) ]     
357     [ORDER BY 排序字段 ASC|DESC ];
358 
359 子查询:    此处规定了在PIVOT()函数操作过程中,所需要使用到的数据(设置子查询确定行和列)。
360 统计函数(列):在转换过程中,设置要进行统计的数据列及统计函数,可以设置多个统计函数。
361 FOR 转换列名称: 将子查询中返回的指定数据变为显示的列。
362 INCLUDE NULLS: 列变为行转换之后保留所有的 null 数据。
363 EXCLUDE NULLS(默认): 列变为行转换之后不保留所有的 null 数据。
364 
365 --范例一 :
366 WITH temp AS(
367     SELECT  * FROM  (SELECT deptno,job,sal FROM emp)
368     PIVOT(
369         SUM(sal)
370         FOR job IN (
371              'PRESIDENT' AS PRESIDENT_JOB,
372               'MANAGER' AS MANAGER_JOB,
373               'ANALYST' AS ANALYST_JOB,
374               'CLERK' AS CLERK_JOB,
375               'SALESMAN' AS SALESMAN_JOB 
376               )
377         ) ORDER BY deptno)
378 SELECT * FROM temp
379 UNPIVOT (
380     sal_sum FOR job IN (
381        PRESIDENT_JOB as 'PRESIDENT', 
382        MANAGER_JOB as 'MANAGER', 
383        ANALYST_JOB as 'ANALYST', 
384        CLERK_JOB as 'CLERK', 
385        SALESMAN_JOB as 'SALESMAN' 
386     )
387 )    ORDER BY deptno;    
388         
389 
390 --范例二 : 显示所有数据 ,
391 WITH temp AS(
392     SELECT  * FROM  (SELECT deptno,job,sal FROM emp)
393     PIVOT(
394         SUM(sal)
395         FOR job IN (
396              'PRESIDENT' AS PRESIDENT_JOB,
397               'MANAGER' AS MANAGER_JOB,
398               'ANALYST' AS ANALYST_JOB,
399               'CLERK' AS CLERK_JOB,
400               'SALESMAN' AS SALESMAN_JOB 
401               )
402         ) ORDER BY deptno)
403 SELECT * FROM temp
404 UNPIVOT  INCLUDE NULLS(
405     sal_sum FOR job IN (
406        PRESIDENT_JOB as 'PRESIDENT', 
407        MANAGER_JOB as 'MANAGER', 
408        ANALYST_JOB as 'ANALYST', 
409        CLERK_JOB as 'CLERK', 
410        SALESMAN_JOB as 'SALESMAN' 
411     )
412 )    ORDER BY deptno;
413 
414 
415 
416 
417 递归查询(层次查询)
418     层次查询是一种确定数据行之间关系结构的一种操作,例如,在现实社会的工作中一定会存在“管理层”、“职员层”这样的基本分层关系,在学校也会分为“教学管理层”、“教师层”、“学生层”这样的三层结构。
419     Oracle 中也可以利用其自身所带的工具实现这样的层次结构,实现的操作语法如下:
420 1 设置层次函数
421     LEVEL ...
422     CONNECT BY [NOCYCLE] PRIOR 连接条件
423     [START WITH 开始条件]3
424 LEVEL:可以根据数据所处的层次结构实现自动的层次编号,例如,1/2/3425 CONNECT BY : 指的是数据之间的连接,例如雇员数据依靠 mgr 找到领导,就是一个连接条件,其中 NOCYCLE 需要结合 CONNECT_BY_ISCYCLE 伪列确定出父子节点循环关系。
426 START WITH : 根节点数据的开始条件。
427 
428 2 主要掌握的知识
429     CONNECT_BY_ISLEAF 伪列:在一个树状结构中,节点会分为两种,即根节点、叶子节点,用户可以利用 CONNECT_BY_ISLEAF 伪列判断某一个节点是根节点还是叶子节点,如果此列返回的是数字0,则表示根节点;如果返回1 ,则表示叶子节点。
430     
431     CONNECT_BY_ROOT 列语句:主要作用是取得某一字段在本次分层中的根节点数据名称,如果按照领导层次划分,则所有数据的根节点都应该是 KING。
432     
433     SYS_CONNECT_BY_PATH(列,char)函数:按照给出的节点关系,自动地将当前根节点中的所有路径进行显示。
434     
435     ORDER SIBLINGS BY 字段语句:因为 ORDER BY 会破坏层次结构,所以使用 ORDER SIBLINGS BY 防止破坏层次结构。
436     
437     CONNECT_BY_ISCYCLE :在进行数据层次设计的过程中,最重要的是根据指定的数据列确定数据间的层次关系,但是有时也可能出现死循环。例如KING的领导是BLAKE,而BLAKE的领导是KING就表示一个循环关系。为了判断循环关系的出现,在Oracle中提供了一个 CONNECT_BY_ISCYCLE 伪列,判断是否出现循环,如果出现循环,则显示1;如果没有出现循环,则显示0 。同时,如果要判断是否为循环节点,还需要 NOCYCLE 支持。
438 
439 --用例1 : 观察分层的基本关系:
440 SELECT empno,LPAD('|-',LEVEL*2,'')||ename empname,mgr ,LEVEL
441 FROM emp
442 CONNECT BY PRIOR empno=mgr
443 START WITH mgr IS NULL;
444     
445 --用例2 : 综合运用
446 SELECT ename,LEAP('|-',LEVEL*2,'')||ename empname ,LEVEL ,
447        DECODE(CONNECT_BY_ISLEAF,0,'根节点',1,'叶子节点') isleaf,
448        DECODE(CONNECT_BY_ISCYCLE,0,'【√】没有循环',1,'[X]存在循环') iscycle
449 FROM emp
450 CONNECT BY NOCYCLE PRIOR empno=mgr
451 START WITH empno=7839
452 ORDER SIBLINGS BY ename;
453 
454 --用例3 : CONNECT_BY_ROOT
455 SELECT empno,LPAD('|-',LEVEL*2,'')||ename empname,mgr ,LEVEL
456     CONNECT_BY_ROOT ename
457 FROM emp
458 CONNECT BY PRIOR empno=mgr
459 START WITH empno=7566;
460        
461 --用例4 : SYS_CONNECT_BY_PATH (常用)
462     SELECT empno,LPAD('|- ',LEVEL*2,' ')||SYS_CONNECT_BY_PATH(ename,' => ')  empname,mgr ,LEVEL,
463         DECODE(CONNECT_BY_ISLEAF,0,'根节点',1,'叶子节点') isleaf
464     FROM emp
465     CONNECT BY PRIOR empno=mgr
466     START WITH mgr IS NULL;

 

posted on 2023-04-03 20:30  言溪清流  阅读(26)  评论(0)    收藏  举报