【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事
【SQL开发实战技巧】系列(二):简单单表查询
【SQL开发实战技巧】系列(三):SQL排序的那些事
【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串&UNION与OR的使用注意事项
【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起
【SQL开发实战技巧】系列(十一):拿几个案例讲讲translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函数
【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数&通过执行计划看sum()over()对员工工资进行累加
【SQL开发实战技巧】系列(十四):计算消费后的余额&计算银行流水累计和&计算各部门工资排名前三位的员工
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
【SQL开发实战技巧】系列(二十):数据仓库中时间类型操作(进阶)获取季度开始结束时间以及如何统计非连续性时间的数据
【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
【SQL开发实战技巧】系列(二十二):数仓报表场景☞ 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
【SQL开发实战技巧】系列(二十四):数仓报表场景☞通过案例执行计划详解”行转列”,”列转行”是如何实现的
【SQL开发实战技巧】系列(二十五):数仓报表场景☞结果集中的重复数据只显示一次以及计算部门薪资差异高效的写法以及如何对数据进行快速分组
【SQL开发实战技巧】系列(二十六):数仓报表场景☞聊聊ROLLUP、UNION ALL是如何分别做分组合计的以及如何识别哪些行是做汇总的结果行
【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表
【SQL开发实战技巧】系列(二十八):数仓报表场景☞人员分布问题以及不同组(分区)同时聚集如何实现
【SQL开发实战技巧】系列(二十九):数仓报表场景☞简单的树形(分层)查询以及如何确定根节点、分支节点和叶子节点
【SQL开发实战技巧】系列(三十):数仓报表场景☞树形(分层)查询如何排序?以及如何在树形查询中正确的使用where条件
【SQL开发实战技巧】系列(三十一):数仓报表场景☞分层查询如何只查询树形结构某一个分支?如何剪掉一个分支?
文章目录
本篇文章讲解的主要内容是:第一个案例给大家介绍在树形(分层)查询中,我们如何只查询出来树形的一个分支?如何剪去分支,不能在WHERE中加条件。
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。
现在有个需求:在分层查询中,我们如何只查询出来树形的一个分支?
说到这里,你会不会脑海中直接想where了?
可惜的是,我们不能用where过滤来做,我们先说一下正确的实现需求的写法:
其实我们用START WITH指定分支的起点就可以啦,看下面查询:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 员工编码,
ename AS 姓名,
mgr AS 主管编码,
(PRIOR ename) AS 主管姓名,
level as 级别,
decode(level, 1, 1) as 根节点,
decode(connect_by_isleaf, 1, 1) as 叶子节点,
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支节点,
deptno as 部门编码,
sys_connect_by_path(ename, '->') as enames
FROM emp
START WITH empno=7566
CONNECT BY (PRIOR empno) = mgr
order siblings by empno;
员工编码 姓名 主管编码 主管姓名 级别 根节点 叶子节点 分支节点 部门编码 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过滤来实现这个需求:
我们用前面的案例说一下,看下面查询:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 员工编码,
ename AS 姓名,
mgr AS 主管编码,
(PRIOR ename) AS 主管姓名,
level as 级别,
decode(level, 1, 1) as 根节点,
decode(connect_by_isleaf, 1, 1) as 叶子节点,
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支节点,
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;
员工编码 姓名 主管编码 主管姓名 级别 根节点 叶子节点 分支节点 部门编码 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
分析上面查询结果,如果我只想要mrg=7566的这个分支结构的数据,用where条件的话,我们上一篇文章说过:“如果你有这种过滤+树形查询的需求,一定一定要先过滤,用子查询嵌套一次,再进行树形查询”
那么接下来我们这么查询:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 员工编码,
ename AS 姓名,
mgr AS 主管编码,
(PRIOR ename) AS 主管姓名,
level as 级别,
decode(level, 1, 1) as 根节点,
decode(connect_by_isleaf, 1, 1) as 叶子节点,
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支节点,
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;
员工编码 姓名 主管编码 主管姓名 级别 根节点 叶子节点 分支节点 部门编码 ENAMES
-------------------------------------------------------------------------------- ---------- ----- ---------- ---------- ---------- ---------- ---------- ---- --------------------------------------------------------------------------------
SQL>
诶嘿,可以看到哈,没结果!!!没查出来任何信息!为什么?因为子查询select * from emp where mgr=7566把根节点empno=7566给过滤掉了,看下子查询结果:
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>
那会不会有人这么想?我把这个根节点empno=7566加上不就得了?如下查询:
SQL> SELECT lpad('->', (level - 1) * 2, '->') || empno AS 员工编码,
2 ename AS 姓名,
3 mgr AS 主管编码,
4 (PRIOR ename) AS 主管姓名,
5 level as 级别,
6 decode(level, 1, 1) as 根节点,
7 decode(connect_by_isleaf, 1, 1) as 叶子节点,
8 CASE
9 WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
10 1
11 END AS 分支节点,
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;
员工编码 姓名 主管编码 主管姓名 级别 根节点 叶子节点 分支节点 部门编码 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)从第一个查询结果看它俩是分支节点呀,他们下面分别有7876,7369呢,而且我是在本节开头的时候给了你确定的答案,揣着答案找肯定明白,但是当你不知道正确答案时候呢?所以说,用where是不行滴!
接上面的案例:
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 员工编码,
ename AS 姓名,
mgr AS 主管编码,
(PRIOR ename) AS 主管姓名,
level as 级别,
decode(level, 1, 1) as 根节点,
decode(connect_by_isleaf, 1, 1) as 叶子节点,
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支节点,
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;
员工编码 姓名 主管编码 主管姓名 级别 根节点 叶子节点 分支节点 部门编码 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
现在有个新的需求:要求剪去7698开始的这个分支。
同样,剪去分支也不能在WHERE中加条件,因为树形查询递归是根据条件(PRIOR empno)=mgr进行的,所以在下列语句加条件就可以。
SELECT lpad('->', (level - 1) * 2, '->') || empno AS 员工编码,
ename AS 姓名,
mgr AS 主管编码,
(PRIOR ename) AS 主管姓名,
level as 级别,
decode(level, 1, 1) as 根节点,
decode(connect_by_isleaf, 1, 1) as 叶子节点,
CASE
WHEN (connect_by_isleaf = 0 AND LEVEL > 1) THEN
1
END AS 分支节点,
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;
员工编码 姓名 主管编码 主管姓名 级别 根节点 叶子节点 分支节点 部门编码 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
本篇文章讲解的主要内容是:第一个案例给大家介绍在树形(分层)查询中,我们如何只查询出来树形的一个分支?如何剪去分支,不能在WHERE中加条件。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta