coo*_*ist 7 sql oracle oracle11g
查询:
select level from dual connect by rownum<10;
Run Code Online (Sandbox Code Playgroud)
给出1到9之间的数字.
另一个疑问:
SELECT LEVEL FROM DUAL CONNECT BY rownum>5;
Run Code Online (Sandbox Code Playgroud)
输出:1
我在管理员/员工等分层数据中使用了CONNECT BY.但我无法解释上述两个查询的结果.
编辑: 我不是试图通过查询#2实现任何特殊功能.我只是想知道oracle如何解释查询.由于使用CONNECT BY,是否有任何部分作为父母和子女?为什么结果为1?幕后发生了什么?
kro*_*lko 12
如何CONNECT BY执行和评估查询 - 逐步(通过示例).
假设我们有下表和connect by query:
select * from mytable;
X
----------
1
2
3
4
SELECT level, m.*
FROM mytable m
START with x = 1
CONNECT BY PRIOR x +1 = x OR PRIOR x + 2 = x
ORDER BY level;
Run Code Online (Sandbox Code Playgroud)
步骤1:
从表mytable中选择满足START WITH条件的行,将LEVEL = 1分配给返回的结果集:
CREATE TABLE step1 AS
SELECT 1 "LEVEL", X from mytable
WHERE x = 1;
SELECT * FROM step1;
LEVEL X
---------- ----------
1 1
Run Code Online (Sandbox Code Playgroud)
第2步
将等级提高1:
LEVEL = LEVEL + 1
Run Code Online (Sandbox Code Playgroud)
mytable使用CONNECT BY条件作为连接条件,加入上一步返回的结果集.
在此子句中PRIOR column-name引用上一步返回的结果集,而简单column-name引用该mytable表:
CREATE TABLE step2 AS
SELECT 2 "LEVEL", mytable.X from mytable
JOIN step1 "PRIOR"
ON "PRIOR".x +1 = mytable.x or "PRIOR".x + 2 = mytable.x;
select * from step2;
LEVEL X
---------- ----------
2 2
2 3
Run Code Online (Sandbox Code Playgroud)
STEP x + 1
重复#2直到最后一个操作返回空结果集.
第3步
CREATE TABLE step3 AS
SELECT 3 "LEVEL", mytable.X from mytable
JOIN step2 "PRIOR"
ON "PRIOR".x +1 = mytable.x or "PRIOR".x + 2 = mytable.x;
select * from step3;
LEVEL X
---------- ----------
3 3
3 4
3 4
Run Code Online (Sandbox Code Playgroud)
第4步
CREATE TABLE step4 AS
SELECT 4 "LEVEL", mytable.X from mytable
JOIN step3 "PRIOR"
ON "PRIOR".x +1 = mytable.x or "PRIOR".x + 2 = mytable.x;
select * from step4;
LEVEL X
---------- ----------
4 4
Run Code Online (Sandbox Code Playgroud)
第5步
CREATE TABLE step5 AS
SELECT 5 "LEVEL", mytable.X from mytable
JOIN step4 "PRIOR"
ON "PRIOR".x +1 = mytable.x or "PRIOR".x + 2 = mytable.x;
select * from step5;
no rows selected
Run Code Online (Sandbox Code Playgroud)
第5步没有返回任何行,所以现在我们最终确定查询
最后一步
UNION ALL 所有步骤的结果并将其作为最终结果返回:
SELECT * FROM step1
UNION ALL
SELECT * FROM step2
UNION ALL
SELECT * FROM step3
UNION ALL
SELECT * FROM step4
UNION ALL
SELECT * FROM step5;
LEVEL X
---------- ----------
1 1
2 2
2 3
3 3
3 4
3 4
4 4
Run Code Online (Sandbox Code Playgroud)
现在让我们将上述过程应用于您的查询:
SELECT * FROM dual;
DUMMY
-----
X
SELECT LEVEL FROM DUAL CONNECT BY rownum>5;
Run Code Online (Sandbox Code Playgroud)
步骤1
由于查询不包含该START WITH子句,因此Oracle会从源表中选择所有记录:
CREATE TABLE step1 AS
SELECT 1 "LEVEL" FROM dual;
select * from step1;
LEVEL
----------
1
Run Code Online (Sandbox Code Playgroud)
第2步
CREATE TABLE step2 AS
SELECT 2 "LEVEL" from dual
JOIN step1 "PRIOR"
ON rownum > 5
select * from step2;
no rows selected
Run Code Online (Sandbox Code Playgroud)
由于最后一步没有返回任何行,我们将最终确定查询.
最后一步
SELECT * FROM step1
UNION ALL
SELECT * FROM step2;
LEVEL
----------
1
Run Code Online (Sandbox Code Playgroud)
最后一个查询的分析:
select level from dual connect by rownum<10;
Run Code Online (Sandbox Code Playgroud)
我作为家庭作业留给你.
这与CONNECT BY无关,而是你滥用ROWNUM的神器.
引用文档:
对于查询返回的每一行,ROWNUM伪列返回一个数字,表示Oracle从一个表或一组连接行中选择行的顺序.选择的第一行的ROWNUM为1,第二行的数量为2,依此类推.
ROWNUM是结果集的一个因子而不是查询.虽然这些是相互关联的,但它们并不完全相同; 如果第一个结果不存在,则第六个结果不可能存在.
这也在文档中解释:
ROWNUM值大于正整数的条件测试始终为false.例如,此查询不返回任何行:
Run Code Online (Sandbox Code Playgroud)SELECT * FROM employees WHERE ROWNUM > 1;获取的第一行被赋予ROWNUM为1并使条件为假.要获取的第二行现在是第一行,并且还指定了ROWNUM为1并使条件为false.所有行随后都无法满足条件,因此不返回任何行.