Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为什么表上的CONNECT BY LEVEL返回额外的行?_Sql_Oracle_Connect By - Fatal编程技术网

Sql 为什么表上的CONNECT BY LEVEL返回额外的行?

Sql 为什么表上的CONNECT BY LEVEL返回额外的行?,sql,oracle,connect-by,Sql,Oracle,Connect By,在表上执行CONNECT BY LEVEL时,使用CONNECT BY似乎返回了太多的行。发生的事情背后的逻辑是什么 假设下表: create table a ( id number ); insert into a values (1); insert into a values (2); insert into a values (3); 此查询返回12行 表A中的每一行LVL列的值为1,表A中的每一行LVL列的值为3,其中LVL列为2,即: ID | LVL ---+----- 1

在表上执行CONNECT BY LEVEL时,使用CONNECT BY似乎返回了太多的行。发生的事情背后的逻辑是什么

假设下表:

create table a ( id number );

insert into a values (1);
insert into a values (2);
insert into a values (3);
此查询返回12行

表A中的每一行LVL列的值为1,表A中的每一行LVL列的值为3,其中LVL列为2,即:

ID | LVL ---+----- 1 | 1 1 | 2 1 | 2 1 | 2 2 | 1 2 | 2 2 | 2 2 | 2 3 | 1 3 | 2 3 | 2 3 | 2 它相当于此查询,它返回相同的结果

 select id, level as lvl
   from dual
  cross join a
connect by level <= 2
  order by id, level
我不明白为什么这些查询返回12行,或者为什么对于ID列的每个值,有三行LVL为2,只有一行LVL为1

为ID.1的每个值增加连接到3的级别数,其中LVL为1、3(其中LVL为2)和9(其中LVL为3)。这似乎表明返回的行数是表A中的行数乘以LVL减1的幂

我认为这些查询将与下面相同,返回 6排


对我来说,在解释应该发生的事情时,问题并不是特别清楚。这些功能发生了什么?为什么前两个查询与第三个查询不一样?

在将最终查询与其他查询进行比较时,您正在将苹果与桔子进行比较,因为该级别与1行双表隔离

让我们考虑这个查询:

 select id, level as lvl
   from a
connect by level <= 2
  order by id, level
这意味着,从表集合select*From a开始。然后,对于返回的每一行,将此行连接到上一行。由于您没有在“连接方式”中定义连接,这实际上是笛卡尔连接,因此,当您有3行1,2,3时,1将连接到2,1->3,2->1,2->3,3->1和3->2,并且它们本身也连接到1->1,2->2和3->3。这些连接的级别为2。我们有9个连接,这就是为什么我们得到12行,3个原始的1级行,加上笛卡尔集

因此,输出的行数=行计数+行计数^2

在上一个查询中,您将隔离此级别

select level  as lvl
           from dual
        connect by level  <= 2

它当然返回2行。然后将其按比例分配到原始的3行,输出6行。

在第一个查询中,您只需按级别进行连接。 所以,如果使用级别的connect by时未使用start with子句和PREVIOR运算符,则对将子行连接到父行没有任何限制。Oracle在这种情况下的做法是,通过将一行连接到更高级别的每一行,返回所有可能的层次排列

SQL> select b
  2       , level as lvl
  3       , sys_connect_by_path(b, '->') as ph
  4     from a
  5  connect by level <= 2
  6  ;

         B        LVL PH
       ---------- ---------- 
         1          1 ->1
         1          2 ->1->1
         2          2 ->1->2
         3          2 ->1->3
         2          1 ->2
         1          2 ->2->1
         2          2 ->2->2
         3          2 ->2->3
         3          1 ->3
         1          2 ->3->1
         2          2 ->3->2
         3          2 ->3->3

12 rows selected

您可以使用以下技巧来解决此问题:

select id, level as lvl
   from a
      left outer join (select level l from dual connect by level <= 2) lev on 1 = 1
order by id

sys_connect_by_path在MySQL5中是否有类似的东西?
SQL> select b
  2       , level as lvl
  3       , sys_connect_by_path(b, '->') as ph
  4     from a
  5  connect by level <= 2
  6  ;

         B        LVL PH
       ---------- ---------- 
         1          1 ->1
         1          2 ->1->1
         2          2 ->1->2
         3          2 ->1->3
         2          1 ->2
         1          2 ->2->1
         2          2 ->2->2
         3          2 ->2->3
         3          1 ->3
         1          2 ->3->1
         2          2 ->3->2
         3          2 ->3->3

12 rows selected
select id, level as lvl
   from a
      left outer join (select level l from dual connect by level <= 2) lev on 1 = 1
order by id