系列文章目錄
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(一):關(guān)于SQL不得不說的那些事
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二):簡(jiǎn)單單表查詢
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(三):SQL排序的那些事
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(四):從執(zhí)行計(jì)劃討論UNION ALL與空字符串&UNION與OR的使用注意事項(xiàng)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(五):從執(zhí)行計(jì)劃看IN、EXISTS 和 INNER JOIN效率,我們要分場(chǎng)景不要死記網(wǎng)上結(jié)論
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(六):從執(zhí)行計(jì)劃看NOT IN、NOT EXISTS 和 LEFT JOIN效率,記住內(nèi)外關(guān)聯(lián)條件不要亂放
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(七):從有重復(fù)數(shù)據(jù)前提下如何比較出兩個(gè)表中的差異數(shù)據(jù)及對(duì)應(yīng)條數(shù)聊起
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(八):聊聊如何插入數(shù)據(jù)時(shí)比約束更靈活的限制數(shù)據(jù)插入以及怎么一個(gè)insert語(yǔ)句同時(shí)插入多張表
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(九):一個(gè)update誤把其他列數(shù)據(jù)更新成空了?Merge改寫update!給你五種刪除重復(fù)數(shù)據(jù)的寫法!
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十):從拆分字符串、替換字符串以及統(tǒng)計(jì)字符串出現(xiàn)次數(shù)說起
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十一):拿幾個(gè)案例講講translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函數(shù)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十二):三問(如何對(duì)字符串字母去重后按字母順序排列字符串?如何識(shí)別哪些字符串中包含數(shù)字?如何將分隔數(shù)據(jù)轉(zhuǎn)換為多值IN列表?)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十三):討論一下常用聚集函數(shù)&通過執(zhí)行計(jì)劃看sum()over()對(duì)員工工資進(jìn)行累加
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十四):計(jì)算消費(fèi)后的余額&計(jì)算銀行流水累計(jì)和&計(jì)算各部門工資排名前三位的員工
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十五):查找最值所在行數(shù)據(jù)信息及快速計(jì)算總和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十六):數(shù)據(jù)倉(cāng)庫(kù)中時(shí)間類型操作(初級(jí))日、月、年、時(shí)、分、秒之差及時(shí)間間隔計(jì)算
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十七):數(shù)據(jù)倉(cāng)庫(kù)中時(shí)間類型操作(初級(jí))確定兩個(gè)日期之間的工作天數(shù)、計(jì)算—年中周內(nèi)各日期出現(xiàn)次數(shù)、確定當(dāng)前記錄和下一條記錄之間相差的天數(shù)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十八):數(shù)據(jù)倉(cāng)庫(kù)中時(shí)間類型操作(進(jìn)階)INTERVAL、EXTRACT以及如何確定一年是否為閏年及周的計(jì)算
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(十九):數(shù)據(jù)倉(cāng)庫(kù)中時(shí)間類型操作(進(jìn)階)如何一個(gè)SQL打印當(dāng)月或一年的日歷?如何確定某月內(nèi)第一個(gè)和最后—個(gè)周內(nèi)某天的日期?
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十):數(shù)據(jù)倉(cāng)庫(kù)中時(shí)間類型操作(進(jìn)階)獲取季度開始結(jié)束時(shí)間以及如何統(tǒng)計(jì)非連續(xù)性時(shí)間的數(shù)據(jù)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十一):數(shù)據(jù)倉(cāng)庫(kù)中時(shí)間類型操作(進(jìn)階)識(shí)別重疊的日期范圍,按指定10分鐘時(shí)間間隔匯總數(shù)據(jù)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十二):數(shù)倉(cāng)報(bào)表場(chǎng)景? 從分析函數(shù)效率一定快嗎聊一聊結(jié)果集分頁(yè)和隔行抽樣實(shí)現(xiàn)方式
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十三):數(shù)倉(cāng)報(bào)表場(chǎng)景? 如何對(duì)數(shù)據(jù)排列組合去重以及通過如何找到包含最大值和最小值的記錄這個(gè)問題再次用執(zhí)行計(jì)劃給你證明分析函數(shù)性能不一定高
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十四):數(shù)倉(cāng)報(bào)表場(chǎng)景?通過案例執(zhí)行計(jì)劃詳解”行轉(zhuǎn)列”,”列轉(zhuǎn)行”是如何實(shí)現(xiàn)的
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十五):數(shù)倉(cāng)報(bào)表場(chǎng)景?結(jié)果集中的重復(fù)數(shù)據(jù)只顯示一次以及計(jì)算部門薪資差異高效的寫法以及如何對(duì)數(shù)據(jù)進(jìn)行快速分組
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十六):數(shù)倉(cāng)報(bào)表場(chǎng)景?聊聊ROLLUP、UNION ALL是如何分別做分組合計(jì)的以及如何識(shí)別哪些行是做匯總的結(jié)果行
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十七):數(shù)倉(cāng)報(bào)表場(chǎng)景?通過對(duì)移動(dòng)范圍進(jìn)行聚集來詳解分析函數(shù)開窗原理以及如何一個(gè)SQL打印九九乘法表
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十八):數(shù)倉(cāng)報(bào)表場(chǎng)景?人員分布問題以及不同組(分區(qū))同時(shí)聚集如何實(shí)現(xiàn)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(二十九):數(shù)倉(cāng)報(bào)表場(chǎng)景?簡(jiǎn)單的樹形(分層)查詢以及如何確定根節(jié)點(diǎn)、分支節(jié)點(diǎn)和葉子節(jié)點(diǎn)
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(三十):數(shù)倉(cāng)報(bào)表場(chǎng)景?樹形(分層)查詢?nèi)绾闻判??以及如何在樹形查詢中正確的使用where條件
【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(三十一):數(shù)倉(cāng)報(bào)表場(chǎng)景?分層查詢?nèi)绾沃徊樵儤湫谓Y(jié)構(gòu)某一個(gè)分支?如何剪掉一個(gè)分支?
前言
本篇文章講解的主要內(nèi)容是:第一個(gè)案例給大家介紹在樹形(分層)查詢中,我們?nèi)绾沃徊樵兂鰜順湫蔚囊粋€(gè)分支?如何剪去分支,不能在WHERE中加條件。
【SQL開發(fā)實(shí)戰(zhàn)技巧】這一系列博主當(dāng)作復(fù)習(xí)舊知識(shí)來進(jìn)行寫作,畢竟SQL開發(fā)在數(shù)據(jù)分析場(chǎng)景非常重要且基礎(chǔ),面試也會(huì)經(jīng)常問SQL開發(fā)和調(diào)優(yōu)經(jīng)驗(yàn),相信當(dāng)我寫完這一系列文章,也能再有所收獲,未來面對(duì)SQL面試也能游刃有余~。
一、如何只查詢樹形的一個(gè)分支
現(xiàn)在有個(gè)需求:在分層查詢中,我們?nèi)绾沃徊樵兂鰜順湫蔚囊粋€(gè)分支?
說到這里,你會(huì)不會(huì)腦海中直接想where了?
可惜的是,我們不能用where過濾來做,我們先說一下正確的實(shí)現(xiàn)需求的寫法:
其實(shí)我們用START WITH
指定分支的起點(diǎn)就可以啦,看下面查詢:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 員工編碼,
ename AS 姓名,
mgr AS 主管編碼,
(PRIOR ename) AS 主管姓名,
level as 級(jí)別,
decode(level, 1, 1) as 根節(jié)點(diǎn),
decode(connect_by_isleaf, 1, 1) as 葉子節(jié)點(diǎn),
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支節(jié)點(diǎn),
deptno as 部門編碼,
sys_connect_by_path(ename, '->') as enames
FROM emp
START WITH empno=7566
CONNECT BY (PRIOR empno) = mgr
order siblings by empno;
員工編碼 姓名 主管編碼 主管姓名 級(jí)別 根節(jié)點(diǎn) 葉子節(jié)點(diǎn) 分支節(jié)點(diǎn) 部門編碼 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
7566 JONES 7839 1 1 20 ->JONES
->7788 SCOTT 7566 JONES 2 1 20 ->JONES->SCOTT
->->7876 ADAMS 7788 SCOTT 3 1 20 ->JONES->SCOTT->ADAMS
->7902 FORD 7566 JONES 2 1 20 ->JONES->FORD
->->7369 SMITH 7902 FORD 3 1 20 ->JONES->FORD->SMITH
說完了正確的寫法,這里給大家說一下為什么不能用where過濾來實(shí)現(xiàn)這個(gè)需求:
我們用前面的案例說一下,看下面查詢:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 員工編碼,
ename AS 姓名,
mgr AS 主管編碼,
(PRIOR ename) AS 主管姓名,
level as 級(jí)別,
decode(level, 1, 1) as 根節(jié)點(diǎn),
decode(connect_by_isleaf, 1, 1) as 葉子節(jié)點(diǎn),
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支節(jié)點(diǎn),
deptno as 部門編碼,
sys_connect_by_path(ename, '->') as enames
FROM emp
START WITH mgr is null
CONNECT BY (PRIOR empno) = mgr
order siblings by empno;
員工編碼 姓名 主管編碼 主管姓名 級(jí)別 根節(jié)點(diǎn) 葉子節(jié)點(diǎn) 分支節(jié)點(diǎn) 部門編碼 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
7839 KING 1 1 10 ->KING
->7566 JONES 7839 KING 2 1 20 ->KING->JONES
->->7788 SCOTT 7566 JONES 3 1 20 ->KING->JONES->SCOTT
->->->7876 ADAMS 7788 SCOTT 4 1 20 ->KING->JONES->SCOTT->ADAMS
->->7902 FORD 7566 JONES 3 1 20 ->KING->JONES->FORD
->->->7369 SMITH 7902 FORD 4 1 20 ->KING->JONES->FORD->SMITH
->7698 BLAKE 7839 KING 2 1 30 ->KING->BLAKE
->->7499 ALLEN 7698 BLAKE 3 1 30 ->KING->BLAKE->ALLEN
->->7521 WARD 7698 BLAKE 3 1 30 ->KING->BLAKE->WARD
->->7654 MARTIN 7698 BLAKE 3 1 30 ->KING->BLAKE->MARTIN
->->7844 TURNER 7698 BLAKE 3 1 30 ->KING->BLAKE->TURNER
->->7900 JAMES 7698 BLAKE 3 1 30 ->KING->BLAKE->JAMES
->7782 CLARK 7839 KING 2 1 10 ->KING->CLARK
->->7934 MILLER 7782 CLARK 3 1 10 ->KING->CLARK->MILLER
14 rows selected
分析上面查詢結(jié)果,如果我只想要mrg=7566的這個(gè)分支結(jié)構(gòu)的數(shù)據(jù),用where條件的話,我們上一篇文章說過:“如果你有這種過濾+樹形查詢的需求,一定一定要先過濾,用子查詢嵌套一次,再進(jìn)行樹形查詢”
那么接下來我們這么查詢:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 員工編碼,
ename AS 姓名,
mgr AS 主管編碼,
(PRIOR ename) AS 主管姓名,
level as 級(jí)別,
decode(level, 1, 1) as 根節(jié)點(diǎn),
decode(connect_by_isleaf, 1, 1) as 葉子節(jié)點(diǎn),
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支節(jié)點(diǎn),
deptno as 部門編碼,
sys_connect_by_path(ename, '->') as enames
FROM (select * from emp where mgr=7566)
START WITH empno=7566
CONNECT BY (PRIOR empno) = mgr
order siblings by empno;
員工編碼 姓名 主管編碼 主管姓名 級(jí)別 根節(jié)點(diǎn) 葉子節(jié)點(diǎn) 分支節(jié)點(diǎn) 部門編碼 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
SQL>
誒嘿,可以看到哈,沒結(jié)果?。?!沒查出來任何信息!為什么?因?yàn)樽硬樵僺elect * from emp where mgr=7566把根節(jié)點(diǎn)empno=7566給過濾掉了,看下子查詢結(jié)果:
SQL> select * from emp where mgr=7566
2 ;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7788 SCOTT ANALYST 7566 1987-4-19 3000.00 20
7902 FORD ANALYST 7566 1981-12-3 3000.00 20
SQL>
那會(huì)不會(huì)有人這么想?我把這個(gè)根節(jié)點(diǎn)empno=7566
加上不就得了?如下查詢:
SQL> SELECT lpad('->', (level - 1) * 2, '->') || empno AS 員工編碼,
2 ename AS 姓名,
3 mgr AS 主管編碼,
4 (PRIOR ename) AS 主管姓名,
5 level as 級(jí)別,
6 decode(level, 1, 1) as 根節(jié)點(diǎn),
7 decode(connect_by_isleaf, 1, 1) as 葉子節(jié)點(diǎn),
8 CASE
9 WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
10 1
11 END AS 分支節(jié)點(diǎn),
12 deptno as 部門編碼,
13 sys_connect_by_path(ename, '->') as enames
14 FROM (select * from emp where mgr=7566 union all select * from emp where empno=7566)
15 START WITH empno=7566
16 CONNECT BY (PRIOR empno) = mgr
17 order siblings by empno;
員工編碼 姓名 主管編碼 主管姓名 級(jí)別 根節(jié)點(diǎn) 葉子節(jié)點(diǎn) 分支節(jié)點(diǎn) 部門編碼 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
7566 JONES 7839 1 1 20 ->JONES
->7788 SCOTT 7566 JONES 2 1 20 ->JONES->SCOTT
->7902 FORD 7566 JONES 2 1 20 ->JONES->FORD
那么問題來了,(7788,7902)從第一個(gè)查詢結(jié)果看它倆是分支節(jié)點(diǎn)呀,他們下面分別有7876,7369呢,而且我是在本節(jié)開頭的時(shí)候給了你確定的答案,揣著答案找肯定明白,但是當(dāng)你不知道正確答案時(shí)候呢?所以說,用where是不行滴!
二、如何正確的剪去一個(gè)分支
接上面的案例:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 員工編碼,
ename AS 姓名,
mgr AS 主管編碼,
(PRIOR ename) AS 主管姓名,
level as 級(jí)別,
decode(level, 1, 1) as 根節(jié)點(diǎn),
decode(connect_by_isleaf, 1, 1) as 葉子節(jié)點(diǎn),
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支節(jié)點(diǎn),
deptno as 部門編碼,
sys_connect_by_path(ename, '->') as enames
FROM emp
START WITH mgr is null
CONNECT BY (PRIOR empno) = mgr
order siblings by empno;
員工編碼 姓名 主管編碼 主管姓名 級(jí)別 根節(jié)點(diǎn) 葉子節(jié)點(diǎn) 分支節(jié)點(diǎn) 部門編碼 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
7839 KING 1 1 10 ->KING
->7566 JONES 7839 KING 2 1 20 ->KING->JONES
->->7788 SCOTT 7566 JONES 3 1 20 ->KING->JONES->SCOTT
->->->7876 ADAMS 7788 SCOTT 4 1 20 ->KING->JONES->SCOTT->ADAMS
->->7902 FORD 7566 JONES 3 1 20 ->KING->JONES->FORD
->->->7369 SMITH 7902 FORD 4 1 20 ->KING->JONES->FORD->SMITH
->7698 BLAKE 7839 KING 2 1 30 ->KING->BLAKE
->->7499 ALLEN 7698 BLAKE 3 1 30 ->KING->BLAKE->ALLEN
->->7521 WARD 7698 BLAKE 3 1 30 ->KING->BLAKE->WARD
->->7654 MARTIN 7698 BLAKE 3 1 30 ->KING->BLAKE->MARTIN
->->7844 TURNER 7698 BLAKE 3 1 30 ->KING->BLAKE->TURNER
->->7900 JAMES 7698 BLAKE 3 1 30 ->KING->BLAKE->JAMES
->7782 CLARK 7839 KING 2 1 10 ->KING->CLARK
->->7934 MILLER 7782 CLARK 3 1 10 ->KING->CLARK->MILLER
14 rows selected
現(xiàn)在有個(gè)新的需求:要求剪去7698開始的這個(gè)分支。
同樣,剪去分支也不能在WHERE中加條件,因?yàn)闃湫尾樵冞f歸是根據(jù)條件(PRIOR empno)=mgr
進(jìn)行的,所以在下列語(yǔ)句加條件就可以。文章來源:http://www.zghlxwxcb.cn/news/detail-412429.html
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 員工編碼,
ename AS 姓名,
mgr AS 主管編碼,
(PRIOR ename) AS 主管姓名,
level as 級(jí)別,
decode(level, 1, 1) as 根節(jié)點(diǎn),
decode(connect_by_isleaf, 1, 1) as 葉子節(jié)點(diǎn),
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支節(jié)點(diǎn),
deptno as 部門編碼,
sys_connect_by_path(ename, '->') as enames
FROM emp
START WITH mgr is null
CONNECT BY (PRIOR empno) = mgr
and empno !=7698
order siblings by empno;
員工編碼 姓名 主管編碼 主管姓名 級(jí)別 根節(jié)點(diǎn) 葉子節(jié)點(diǎn) 分支節(jié)點(diǎn) 部門編碼 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
7839 KING 1 1 10 ->KING
->7566 JONES 7839 KING 2 1 20 ->KING->JONES
->->7788 SCOTT 7566 JONES 3 1 20 ->KING->JONES->SCOTT
->->->7876 ADAMS 7788 SCOTT 4 1 20 ->KING->JONES->SCOTT->ADAMS
->->7902 FORD 7566 JONES 3 1 20 ->KING->JONES->FORD
->->->7369 SMITH 7902 FORD 4 1 20 ->KING->JONES->FORD->SMITH
->7782 CLARK 7839 KING 2 1 10 ->KING->CLARK
->->7934 MILLER 7782 CLARK 3 1 10 ->KING->CLARK->MILLER
8 rows selected
總結(jié)
本篇文章講解的主要內(nèi)容是:第一個(gè)案例給大家介紹在樹形(分層)查詢中,我們?nèi)绾沃徊樵兂鰜順湫蔚囊粋€(gè)分支?如何剪去分支,不能在WHERE中加條件。文章來源地址http://www.zghlxwxcb.cn/news/detail-412429.html
到了這里,關(guān)于【SQL開發(fā)實(shí)戰(zhàn)技巧】系列(三十一):數(shù)倉(cāng)報(bào)表場(chǎng)景?分層查詢?nèi)绾沃徊樵儤湫谓Y(jié)構(gòu)某一個(gè)分支?如何剪掉一個(gè)分支?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!