繁体   English   中英

使用Oracle语法从Postgres编写数组函数

[英]Write the array function from Postgres in Oracle Syntax

在Postgres中,我会这样做:

SELECT main.*
    , array(SELECT columnA FROM tableB alt WHERE alt.columnB = main.columnB) AS columnAs_to_tableA
FROM tableA main

在Oracle 10中如何做同样的事情? 应当指出,我不能使用listagg。 我找到了一个类似问题的答案: Oracle 10g中的聚合字符串连接我完全不知道此答案的工作方式,也不知道这是否真的是“正确的”解决方案,因为它从未被标记为已回答/接受。

我想用一个示例来回答这个问题,该示例使用我提供的一对一比较的相同表名,对于寻求相同答案的其他人来说可能是最好的。

谢谢

编辑1:我应该补充一点,我想避免引入新的架构元素,例如表,函数等。

编辑2:删除数组的要求。 以逗号分隔的字符串就足够了。

如果要返回集合,则需要创建一个类型,然后使用collect来填充该类型。

CREATE TYPE typ_columnA_nt
    AS TABLE OF <<columnA data type>>

然后可以使用collect功能

SELECT main.*
    , cast( collect(SELECT columnA 
                      FROM tableB alt 
                    WHERE alt.columnB = main.columnB)
            as typ_columnA_nt ) AS columnAs_to_tableA
FROM tableA main

如果要返回光标,可以使用cursor功能

SELECT main.*,
       cursor( SELECT columnA
                 FROM tableB alt
                WHERE alt.columnB = main.columnB ) as columnAs_to_tableA
  FROM tableA main

如果要返回用逗号分隔的字符串,Tim Hall 在Oracle中提供了规范的字符串聚合技术列表。 在无法使用listagg版本中,我更喜欢创建一个用户定义的聚合函数 ,该函数可让您

select main.*,
       (select string_agg(columnA)
          from tableB alt
         where alt.columnB = main.columnB) as columnAs_to_tableA
  from tableA main 

如果您限于不涉及创建新对象的解决方案,则最简单的选择是使用wm_concat尽管这不受官方支持

select main.*,
       (select wm_concat(columnA)
          from tableB alt
         where alt.columnB = main.columnB) as columnAs_to_tableA
  from tableA main 

如果您无法创建任何支持对象,并且无法使用不受支持的功能,那么您将sys_connect_by_path于旧的row_numbersys_connect_by_path选项 ,该选项有些丑陋。 我认为您想要这样的东西,但是我犯了一个很小的语法错误的可能性很大。

select main.*,
       agg.value_string
  from tableA main
       left join (select alt_outer.columnB,
                         ltrim(max(sys_connect_by_path(alt_outer.columnA,','))
                                  keep( dense_rank last order by alt_outer.columnA ),
                               ',') as value_string
                    from (select alt.columnA,
                                 alt.columnB,
                                 row_number() over (partition by alt.columnB
                                                        order by alt.columA) as curr,  
                                 row_number() over (partition by alt.columnB
                                                        order by alt.columA) -1 as prev
                            from tableB alt) alt_outer
                    group by alt_outer.columnB
                  connect by alt_outer.prev = prior alt_outer.curr
                         and alt_outer.columnB = prior alt_outer.columnB
                    start with alt_outer.curr = 1) agg
         on( main.columnB = agg.columnB )

另一个选择是使用XML函数

SELECT main.* , 
       tableB_alt.list AS columnAs_to_tableA 
  FROM tableA main 
       LEFT JOIN ( SELECT columnB ,
                          TRIM(TRAILING ',' 
                                 FROM 
                                 XMLAGG(
                                   XMLELEMENT(E,columnA||',')
                                 ).EXTRACT('//text()')
                              ) list 
                     FROM tableB 
                    GROUP BY columnB ) tableB_alt 
         ON tableB_alt.columnB = main.columnB

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM