根据列值的顺序连接列值

Concatenating Column Values Based on Order of Column Values

我正在尝试找出一种方法,将拥有与联名账户持有人相同的人的账户组合在一起。一个账户有 1 个主要人和最多 4 个额外的联名账户持有人。考虑以下示例:

Account Primary Joint1 Joint2 Joint3 Joint4
123 Mark Tim Jim Brian John
124 Mark Jim Tim Brian John
134 Jim Mark Tim Brian John
324 Ann Shelly Helen
168 Shelly Ann Helen

所以在上面:

我正在考虑通过使用 case 语句对 Primary 和 Joint%s 进行排序,然后将顺序连接成一个字符串,然后我可以对其进行分组来解决这个问题。所以在 Ann、Shelly 和 Helen 的情况下——按字母顺序排列它们会给我 Ann、Helen 和 Shelly,我会将这些名字连接在一起以获得“AnnHelenShelly”并按此字符串分组。我已经开始这样做,但当我遇到一个账户有 3 或 4 个联名持有人的情况时,我发现它有点混乱。对于只有一个主关节和一个关节的情况,我只做类似的事情:

case when num_joints = 1 then least(primary, joint1) ||最大的(主要的,联合1) 当 num_joints = 2 时 least(primary, joint1, joint2) || (当 joint1 > least(primary, joint1, joint2) 并且 joint1 < greatest(primary, joint1, joint2) 然后 joint1 当 joint2 > least(primary, joint1, joint2) and joint2 < greatest(primary, joint1, joint2) then joint2 else primary end ||最大(主要,关节 1,关节 2)

但我想知道是否有更简单、更可扩展的方法来执行此操作,这样当我到达 num_joints = 3 或 4 时,它不会太混乱。或者也许还有另一种方法可以对其进行分组,而不必创建由主要持有人和联合持有人按顺序组成的字符串。

一些其他注意事项:

使用 UNPIVOT 将列转换为行,然后使用 LISTAGG 按字母顺序聚合每个帐户的名称,然后再次使用 LISTAGG 聚合每个唯一列表的帐户名字。

此解决方案仍然有点复杂,并不比您的 CASE 版本简单得多,但它确实可以很好地扩展,并且向解决方案添加另一列是微不足道的。该示例使用 LISTAGG,这非常适合显示结果,但如果您要在数据库中处理结果,您的最终生产版本可能不应该使用 LISTAGG

示例架构

create table accounts
(
    account number,
    primary varchar2(100),
    joint1 varchar2(100),
    joint2 varchar2(100),
    joint3 varchar2(100),
    joint4 varchar2(100)
);

insert into accounts
select 123, 'Mark'  ,'Tim'   ,'Jim'  ,'Brian','John' from dual union all
select 124, 'Mark'  ,'Jim'   ,'Tim'  ,'Brian','John' from dual union all
select 134, 'Jim'   ,'Mark'  ,'Tim'  ,'Brian','John' from dual union all
select 324, 'Ann'   ,'Shelly','Helen',''     ,''     from dual union all
select 168, 'Shelly','Ann'   ,'Helen',''     ,''     from dual;

查询

--Accounts per group.
select names, listagg(account, ',') within group (order by account) accounts
from
(
    --Aggregate names into alphabetical list per account.
    select
        account,
        listagg(account_name, ',') within group (order by account_name) names
    from
    (
        --Unpivot columns into rows.
        select account, account_type, account_name
        from accounts
        unpivot (account_name for account_type in
            (primary as 'primary', joint1 as 'join1', joint2 as 'joint2', joint3 as 'joint3', joint4 as 'joint4')
        )
    )
    group by account
)
group by names
order by names;

结果

NAMES                     ACCOUNTS
-----------------------   -----------
Ann,Helen,Shelly          168,324
Brian,Jim,John,Mark,Tim   123,124,134