oracle 如何在创建视图期间将行合并为一列

fiei3ece  于 2023-03-17  发布在  Oracle
关注(0)|答案(2)|浏览(159)

我遇到了一个问题,我想联接几个表来创建一个新视图。到目前为止,该视图工作正常,但我遇到了以下问题:
我有一个名为“MyTable1”的表。此表中有一个ID。我有第二个名为“MyTable2”的表。此表通过ID列引用到“MyTable1”。
我的表格1:

ID
567

我的表格2:

ID    MyTable1_ID    object_ID
1     567            896
2     567            967
3     567            756

代码:

SELECT
MyTable1.ID,
MyTable2.ID,
MyTable2.object_ID
FROM
MyTable1
LEFT JOIN MyTable2 ON MyTable2.MyTable1_ID = MyTable1.ID

输出:

MyTable1.ID      MyTable2.ID     MyTable2.object_ID
567              1               896
567              2               967
567              3               756

预期输出:

MyTable1.ID      MyTable2.ID     MyTable2.object_ID
567              1;2;3           896;967;756

我尝试使用LISTAGG,但也只得到3行输出:

SELECT
MyTable1.ID,
MyTable2.ID,
MyTable2.object_ID
CASE WHEN (SELECT count(*) FROM MyTable2 JOIN MyTable1 ON MyTable2.MyTable1_ID = MyTable1.ID having count(*) > 1) > 1 THEN LISTAGG(MyTable2.object_id, '; ') WITHIN GROUP (order by MyTable2.object_id) ELSE MyTable2.object_id END
FROM
MyTable1
LEFT JOIN MyTable2 ON MyTable2.MyTable1_ID = MyTable1.ID

有人能帮帮我吗?
谢谢

fnx2tebb

fnx2tebb1#

SELECT
MyTable1.ID,
listagg(MyTable2.ID,';') within group(order by MyTable2.ID) tab2_id
listagg(MyTable2.object_ID,';') within 
   group(order by MyTable2.object_ID) tab2_object_id
FROM
MyTable1
LEFT JOIN MyTable2 ON MyTable2.MyTable1_ID = MyTable1.ID
group by MyTable1.ID
order by 1;

但是,要注意,如果连接长度不超过4000个字符,listagg也可以工作。
因此,在Oracle livesql中,我运行了以下命令:

with tab1 (id) as (
  select 567 from dual
)
,tab2 (id,tab1_id,object_id) as (
  select 1, 567, 896 from dual union all
  select 2, 567, 998 from dual union all
  select 3, 567, 777 from dual
)
select tab1.id
 ,listagg(tab2.id,';') within group(order by tab2.id) tab_ids
 ,listagg(tab2.object_id,';') within group(order by tab2.object_id) 
tab_object_ids 
from tab1
left join tab2 on tab1.id=tab2.tab1_id
group by  tab1.id
order by 1

然后运行它只显示了一行。不明白你怎么说它为你获取了三行。

bxjv4tth

bxjv4tth2#

提供了样本数据:

WITH
    t1 AS
        (   Select 567 "ID" From Dual   ), 
    t2 AS
        (
            Select 1 "ID", 567 "MY_T1_ID", 896 "OBJECT_ID" From Dual Union All
            Select 2 "ID", 567 "MY_T1_ID", 967 "OBJECT_ID" From Dual Union All
            Select 3 "ID", 567 "MY_T1_ID", 756 "OBJECT_ID" From Dual 
        )

如果您可以使用不带OVER(Partition By t1.ID)的LISTAGG()分析函数:

Select  t1.ID, 
        LISTAGG(t2.ID, ';') WITHIN GROUP (Order By t2.ID)  "MY_T2_ID",
        LISTAGG(t2.OBJECT_ID, ';') WITHIN GROUP (Order By t2.ID) "MY_T2_OBJECT_ID"
From    t1
Inner Join t2 ON(t2.MY_T1_ID = t1.ID)

Result:
ID   MY_T2_ID  MY_T2_OBJECT_ID
---  --------  ---------------
567  1;2;3     896;967;756

越有可能需要按t1.ID进行分区,则应使用DISTINCT关键字排除重复行(对于大数据集,性能成本可能较高):

Select  DISTINCT t1.ID, 
        LISTAGG(t2.ID, ';') WITHIN GROUP (Order By t2.ID)  OVER (Partition By t1.ID) "MY_T2_ID",
        LISTAGG(t2.OBJECT_ID, ';') WITHIN GROUP (Order By t2.ID) OVER (Partition By t1.ID) "MY_T2_OBJECT_ID"
From    t1
Inner Join t2 ON(t2.MY_T1_ID = t1.ID)

如果是这种情况,你可以这样做:

Select ID, Max(MY_T2_ID) "MY_T2_ID", Max(MY_T2_OBJECT_ID) "MY_T2_OBJECT_ID"
From
    (
        Select  t1.ID, 
                LISTAGG(t2.ID, ';') WITHIN GROUP (Order By t2.ID)  OVER (Partition By t1.ID) "MY_T2_ID",
                LISTAGG(t2.OBJECT_ID, ';') WITHIN GROUP (Order By t2.ID) OVER (Partition By t1.ID) "MY_T2_OBJECT_ID"
        From    t1
        Inner Join t2 ON(t2.MY_T1_ID = t1.ID)
    )
Group By ID

Result:
ID   MY_T2_ID  MY_T2_OBJECT_ID
---  --------  ---------------
567  1;2;3     896;967;756

相关问题