9

查询:

select level from dual connect by rownum<10;

给出从 1 到 9 的数字。

另一个查询:

SELECT LEVEL FROM DUAL CONNECT BY rownum>5;

输出:1

我在经理/员工等分层数据中使用了 CONNECT BY。但我无法解释上述两个查询的结果。

编辑: 我不想通过查询#2 来实现任何特别的目的。我只想知道 oracle 如何解释查询。由于使用了 CONNECT BY,是否有任何部分充当父子关系?为什么结果是 1?幕后发生了什么?

4

2 回答 2

15

如何CONNECT BY执行和评估查询 - 一步一步(通过示例)。

假设我们有下表和一个通过查询连接:

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;

步骤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

第2步

将等级提高 1:

LEVEL = LEVEL + 1

mytable使用CONNECT BY条件作为连接条件连接上一步返回的结果集。

在这个子句PRIOR column-name中指的是上一步返回的结果集,simplecolumn-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

步骤 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

第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 

第 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

第 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 

现在让我们将上述过程应用于您的查询:

SELECT * FROM dual;

DUMMY
-----
X 

SELECT LEVEL FROM DUAL CONNECT BY rownum>5;

步骤1

由于查询不包含该START WITH子句,Oracle 会从源表中选择所有记录:

CREATE TABLE step1 AS
SELECT 1 "LEVEL" FROM dual;

select * from step1;

     LEVEL
----------
         1 

第2步

CREATE TABLE step2 AS
SELECT 2 "LEVEL" from dual
JOIN step1 "PRIOR"
ON rownum > 5

select * from step2;

no rows selected

由于最后一步没有返回任何行,我们将完成我们的查询。

最后一步

SELECT * FROM step1
UNION ALL

SELECT * FROM step2;

     LEVEL
----------
         1

最后一个查询的分析:

select level from dual connect by rownum<10;

我把作业留给你。

于 2013-09-02T20:20:34.447 回答
6

这与 CONNECT BY 无关,而是您滥用 ROWNUM 的产物。

文档中引用:

对于查询返回的每一行,ROWNUM 伪列返回一个数字,指示 Oracle 从表或连接行集中选择行的顺序。选择的第一行的 ROWNUM 为 1,第二行为 2,依此类推。

ROWNUM 是结果集而不是查询的一个因素。尽管这些是相互联系的,但它们并不完全相同;如果第一个结果不存在,则第6结果不可能存在。

这也在文档中进行了解释:

大于正整数的 ROWNUM 值的条件测试始终为假。例如,此查询不返回任何行:

SELECT *
  FROM employees
  WHERE ROWNUM > 1;

提取的第一行被指定为 1 的 ROWNUM 并使条件为假。要获取的第二行现在是第一行,并且还分配了 1 的 ROWNUM 并使条件为假。随后所有行都不满足条件,因此不返回任何行。

于 2013-09-02T12:13:38.557 回答