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 --分析函数中三中子句的组合顺序: 22 第 1 种组合: 函数名称([参数,...]) OVER(PARTITION BY 子句,ORDER BY 子句,WINDOWING 子句)。 23 第 2 种组合: 函数名称([参数,...]) OVER(PARTITION BY 子句,ORDER BY 子句)。 24 第 3 种组合: 函数名称([参数,...]) OVER(PARTITION BY 子句)。 25 第 4 种组合: 函数名称([参数,...]) OVER(ORDER BY 子句,WINDOWING 子句)。 26 第 5 种组合: 函数名称([参数,...]) OVER(ORDER BY 子句)。 27 第 6 种组合: 函数名称([参数,...]) 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/3。 425 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;
浙公网安备 33010602011771号