SELECT列表中子查询内的不同LISTAGG

时间:2015-01-07 10:21:59

标签: sql oracle aggregate-functions aggregate

以下是我尝试做的事情以及我得到的最简单的工作示例:

我的查询如下:

/*
with tran_party as -- ALL DUMMY DATA ARE IN THESE CTE FOR YOUR REFERENCE
         (select 1 tran_party_id, 11 transaction_id, 101 team_id_redirect
            from dual
          union all
          select 2, 11, 101 from dual
          union all
          select 3, 11, 102 from dual
          union all
          select 4, 12, 103 from dual
          union all
          select 5, 12, 103 from dual
          union all
          select 6, 12, 104 from dual
          union all
          select 7, 13, 104 from dual
          union all
          select 8, 13, 105 from dual),
     tran as
         (select 11 transaction_id, 1001 account_id, 1034.93 amount from dual
          union all
          select 12, 1001, 2321.89 from dual
          union all
          select 13, 1002, 3201.47 from dual),
     account as
         (select 1001 account_id, 111 team_id from dual
          union all
          select 1002, 112 from dual),
     team as
         (select 101 team_id, 'UUU' as team_code from dual
          union all
          select 102, 'VV' from dual
          union all
          select 103, 'WWW' from dual
          union all
          select 104, 'XXXXX' from dual
          union all
          select 105, 'Z' from dual)
-- */
-- The Actual Query
select a.account_id,
       t.transaction_id,
       (select listagg (tm_redir.team_code, ', ')
                   within group (order by tm_redir.team_code)
          from tran_party tp_redir
               inner join team tm_redir
                   on tp_redir.team_id_redirect = tm_redir.team_id
               inner join tran t_redir
                   on tp_redir.transaction_id = t_redir.transaction_id
         where     t_redir.account_id = a.account_id
               and t_redir.transaction_id != t.transaction_id)
           as teams_redirected
  from tran t inner join account a on t.account_id = a.account_id;
  

注意: tran_party.team_id_redirect 是引用 team.team_id 的外键。

当前输出:

ACCOUNT_ID TRANSACTION_ID TEAMS_REDIRECTED
---------- -------------- ----------------
1001       11             WWW, WWW, XXXXX
1001       12             UUU, UUU, VV
1002       13

预期输出:

我希望TEAMS_REDIRECTED列中重复的项目只选择一次,如下所示:

ACCOUNT_ID TRANSACTION_ID TEAMS_REDIRECTED
---------- -------------- ----------------
1001       11             WWW, XXXXX
1001       12             UUU, VV
1002       13

我尝试了什么:

我没有直接从tran_party中选择,而是编写了一个内联视图,从tran_party中选择不同的值,如下所示:

select a.account_id,
       t.transaction_id,
       (select listagg (tm_redir.team_code, ', ')
                   within group (order by tm_redir.team_code)
          from (select distinct transaction_id, team_id_redirect -- Note this inline view
                  from tran_party) tp_redir
               inner join team tm_redir
                   on tp_redir.team_id_redirect = tm_redir.team_id
               inner join tran t_redir
                   on tp_redir.transaction_id = t_redir.transaction_id
         where     t_redir.account_id = a.account_id
               and t_redir.transaction_id != t.transaction_id)
           as teams_redirected
  from tran t inner join account a on t.account_id = a.account_id;

虽然这确实给了我预期的输出,但是当我在实际代码中使用这个解决方案时,只需要13秒来检索一行。因此,我不能使用我已经尝试过的东西。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

以下方法摆脱了内联视图以获取重复项,它使用REGEXP_REPLACE函数上的RTRIMLISTAGG来获取{{1}中的不同结果集}}。因此,它不会进行多次扫描。

将此片段添加到您的代码中

aggregated list

修改后的查询 -

RTRIM(REGEXP_REPLACE(listagg (tm_redir.team_code, ',') 
                     WITHIN GROUP (ORDER BY tm_redir.team_code),
                     '([^,]+)(,\1)+', '\1'),
                     ',')
相关问题