Oracle:功能表如何在交叉连接中工作?

时间:2018-03-18 15:36:26

标签: oracle cross-join

我探索了将列中的逗号分隔列表展开为行的技术:

with tbl as (
             select 1 id, 'a,b'   lst from dual
   union all select 2 id, 'c'     lst from dual
   union all select 3 id, 'e,f,g' lst from dual)
select
  tbl.ID
  , regexp_substr(tbl.lst, '[^,]+', 1, lvl.column_value) elem
  , lvl.column_value lvl
from
  tbl
  , table(cast(multiset(
     select level from dual
     connect by level <= regexp_count(tbl.lst, ',')+1) as sys.odcinumberlist)) lvl;

结果是:

ID      ELEM    LVL
1       a       1
1       b       2
2       c       1
3       e       1
3       f       2
3       g       3

正如您所看到的,LVL取决于regexp_count的值,因此交叉连接中的第二个功能表首先由 参数化

它是如何工作的?怎么称呼?我可以根据交叉连接中的前两个来参数化第三个表吗?

参数化仅限于交叉连接,还是可以在join语法中应用?

参考:Splitting string into multiple rows in Oracle

1 个答案:

答案 0 :(得分:1)

来自documentation

  

LATERAL
  指定LATERAL以将子查询指定为横向内联   图即可。在横向内联视图中,您可以指定显示的表   在查询的FROM子句中的横向内联视图的左侧。   您可以在子查询中的任何位置指定此左关联(例如   作为SELECT,FROM和WHERE子句)以及任何嵌套级别。

-- a variation of the query in your question ...
select
  dt.id
, dt.list
, regexp_substr( dt.list, '[^,]+', 1, dt2.lvl ) elements
, dt2.lvl
from (
    select 1 id, 'a,b' list  from dual union all
    select 2, 'c'            from dual union all
    select 3, 'e,f,g'        from dual
) dt, lateral (
    select level lvl from dual
    connect by level <= regexp_count(dt.list, ',') + 1 
) dt2
;

-- output
ID  LIST   ELEMENTS  LVL  
1   a,b    a         1    
1   a,b    b         2    
2   c      c         1    
3   e,f,g  e         1    
3   e,f,g  f         2    
3   e,f,g  g         3  

3个表的示例:

--drop table t1 ;
--drop table t2 ;
--drop table t3 ;

-- tables/data
create table t1 
as
select 1 id, 'a' letter from dual union all
select 2, 'b' from dual union all
select 3, 'c' from dual ;

create table t2 
as
select 1 id, 'd' letter from dual union all
select 2, 'e' from dual union all
select 3, 'f' from dual ;

create table t3 
as
select 1 id, 'g' letter from dual union all
select 2, 'h' from dual union all
select 3, 'i' from dual ;

-- query
select *
from 
  t1
, lateral ( select letter from t2 where id = t1.id ) t2
, lateral ( select letter from t3 where id = t2.id )
;

-- output
ID  LETTER  LETTER  LETTER  
1   a       d       g       
2   b       e       h       
3   c       f       i  

另外(使用相同的表格)

-- reference t1 <- t2, 
-- reference t1 and t2 <- t3
select *
from 
  t1
, lateral ( select letter from t2 where id = t1.id ) t2
, lateral ( select letter || t1.letter from t3 where id = t2.id )
;

-- output
ID  LETTER  LETTER  LETTER||T1.LETTER  
1   a       d       ga                 
2   b       e       hb                 
3   c       f       ic  

而“标准”交叉联接会给我们......

select *
from 
  t1 cross join t2 cross join t3
; 

ID  LETTER  ID  LETTER  ID  LETTER  
1   a       1   d       1   g       
1   a       1   d       2   h       
1   a       1   d       3   i       
1   a       2   e       1   g       
1   a       2   e       2   h       
1   a       2   e       3   i   
...
-- 27 rows

相关主题:交叉申请(请参阅文档和示例here)。