根据要求连接或隔离字符串

时间:2017-07-07 14:17:38

标签: sql oracle oracle11g string-concatenation listagg

USER_ID     COLUMN1       COLUMN2

JOHN          24           CA
JOHN          24           LA
JOHN          63           CA
JOHN          63           LA
JOHN          66           CA
JOHN          66           LA
JOHN           9           AF
JOHN           9           AL
JOHN           9           AW
JOHN           9           DF

必需的输出:

USER_ID          RESULT

JOHN             24~CA-LA  +  63~CA-LA  + 66~CA-LA +  9~AF-AL-AW-DF

这是我的要求。我正在尝试listagg()

select USER_ID,
   (listagg(case when seqnum_p = 1 then COLUMN1 end, '-') within group (order by COLUMN1) ||
    '~' ||
    listagg(case when seqnum_b = 1 then COLUMN2 end, '-') within group (order by COLUMN2)
   ) as result
from (select TABLE.*,
         row_number() over (partition by USER_ID, COLUMN1 order by COLUMN1) as seqnum_p,
         row_number() over (partition by USER_ID, COLUMN2 order by COLUMN2) as seqnum_b
  from TABLE
 )
group by USER_ID;

当前输出:

JOHN         ||       AF-AL-AW-CA-DF-LA~24-63-66-9

1 个答案:

答案 0 :(得分:2)

您可以执行两个级别的聚合,而不是处理行号:

select user_id,
  listagg(tmp, ' + ') within group (order by tmp) as result
from (
  select user_id,
    column1 ||'~'|| listagg(column2, '-') within group (order by column2) as tmp
  from your_table
  group by user_id, column1
)
group by user_id
order by user_id;

USER RESULT                                            
---- --------------------------------------------------
JOHN 24~CA-LA + 63~CA-LA + 66~CA-LA + 9~AF-AL-AW-DF    

内部查询为您提供第一级:

USER TMP                                               
---- --------------------------------------------------
JOHN 9~AF-AL-AW-DF                                     
JOHN 24~CA-LA                                          
JOHN 63~CA-LA                                          
JOHN 66~CA-LA                                          

,外层进一步将每个用户聚合成一个字符串。

外部查询聚合中的order-by是一个以数字开头的字符串,它将'9~...'放在'24~...'之后,这通常是奇数,但似乎是您所期望的。

如果你真的想要它们以数字列-1顺序,你可以在子查询中包含它并使用它进行排序:

select user_id,
  listagg(tmp, ' + ') within group (order by column1) as result
from (
  select user_id, column1,
    column1 ||'~'|| listagg(column2, '-') within group (order by column2) as tmp
  from your_table
  group by user_id, column1
)
group by user_id
order by user_id;

USER RESULT                                            
---- --------------------------------------------------
JOHN 9~AF-AL-AW-DF + 24~CA-LA + 63~CA-LA + 66~CA-LA