【问题标题】:Oracle: How functional table works in cross join?Oracle:功能表如何在交叉连接中工作?
【发布时间】:2018-08-27 05:34:47
【问题描述】:

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

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

【问题讨论】:

    标签: oracle cross-join


    【解决方案1】:

    来自documentation

    横向
    指定 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)。

    【讨论】:

      猜你喜欢
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-22
      • 2011-07-20
      相关资源
      最近更新 更多