oracle sql中的非重复值

watbbzwu  于 2023-04-20  发布在  Oracle
关注(0)|答案(3)|浏览(147)

如何在oracle sql中创建不同的值?
我的表结构如下:
| 用户|acc_1|acc_2|acc_3|acc_4|
| --------------|--------------|--------------|--------------|--------------|
| 1|T1|T1|||
| 二|T2||T2|T2|
| 三||T3|||

create table myTable (user, acc_1, acc_2,acc_3,acc_4) as
 select   1, t1, t1, null,null from dual union all
select   2, t2, null, t2,t2  from dual union all
select   3, null, t3, null,null  from dual ;

当我运行查询时:

select user, acc_1 || ','||acc_2||','||acc_3||','||acc_4 as acc
from myTable

我得到的输出为:
| 用户|行政协调委员会|
| --------------|--------------|
| 1|t1,t1,,|
| 二|t2,,t2,t2|
| 三|,t3,,|
但我不需要acc. I的重复我需要我的输出为:
| 用户|行政协调委员会|
| --------------|--------------|
| 1|T1|
| 二|T2|
| 三|T3|
这可能吗?

slhcrj9b

slhcrj9b1#

最简单的方法是“unpivot”你的数据,并将其视为行。例如:

with unpivot_data as (
select user_, acc_1 acc from myTable where acc_1  is not null
union all
select user_, acc_2 from myTable where acc_2 is not null
union all
select user_, acc_3 from myTable where acc_3 is not null
union all
select user_, acc_4 from myTable where acc_4 is not null
  )
select user_, listagg(distinct acc, ', ') 
  from unpivot_data
 group by user_

在这里,我将数据转换为行,并使用LISTAGG(DISTINCT ...)连接它们。
演示here
当然,你也可以在这里使用UNPIVOT

**编辑:**正如@Littlefoot正确指出的,建议的解决方案不适用于旧版本的Oracle。对于旧版本的Oracle,可以使用UNION代替UNION ALL,并在聚合函数中跳过DISTINCT

with unpivot_data as (
select user_, acc_1 acc from myTable where acc_1  is not null
union 
select user_, acc_2 from myTable where acc_2 is not null
union 
select user_, acc_3 from myTable where acc_3 is not null
union 
select user_, acc_4 from myTable where acc_4 is not null
  )
select user_, listagg(acc, ', ')  WITHIN GROUP (order by acc)
  from unpivot_data
 group by user_
qcbq4gxm

qcbq4gxm2#

给定样本数据:

create table myTable ("USER", acc_1, acc_2,acc_3,acc_4) as
select 1, 't1', 't1', null, null from dual union all
select 2, 't2', null, 't2', 't2' from dual union all
select 3, null, 't3', null, null from dual;

您可以使用CASE表达式(这是更多的类型,但只需要一个表扫描,并使用简单,快速的比较):

SELECT "USER",
          CASE WHEN acc_1 IS NOT NULL
          THEN acc_1 || ',' END
       || CASE WHEN acc_2 IS NOT NULL
               AND  (acc_1 IS NULL OR acc_1 <> acc_2)
               THEN acc_2 || ',' END
       || CASE WHEN acc_3 IS NOT NULL
               AND  (acc_1 IS NULL OR acc_1 <> acc_3)
               AND  (acc_2 IS NULL OR acc_2 <> acc_3)
               THEN acc_3 || ',' END
       || CASE WHEN acc_4 IS NOT NULL
               AND  (acc_1 IS NULL OR acc_1 <> acc_4)
               AND  (acc_2 IS NULL OR acc_2 <> acc_4)
               AND  (acc_3 IS NULL OR acc_3 <> acc_4)
               THEN acc_4 || ',' END AS accounts
FROM   myTable;

其输出:
| 使用者|账户|
| --------------|--------------|
| 1|t1,|
| 二|t2,|
| 三|t3,|

  • 注意:如果您想删除结尾的逗号,那么您可以使用RTRIM(或SUBSTR,如果帐户号码可能包含逗号,则直到倒数第二个字符)。

或者,unpivot和重新聚合行(这要少得多,但与使用CASE表达式在初始行上执行所有操作相比,unpivot和重新聚合的效率要低得多):

SELECT "USER",
       LISTAGG(DISTINCT acc) WITHIN GROUP (ORDER BY type) AS accounts
FROM   myTable
UNPIVOT (acc FOR type IN (acc_1, acc_2, acc_3, acc_4))
GROUP BY "USER"

其输出:
| 使用者|账户|
| --------------|--------------|
| 1|T1|
| 二|T2|
| 三|T3|
fiddle

yjghlzjz

yjghlzjz3#

只需使用COALESCE为每个用户选择第一个非空的acc值:

select user, coalesce(acc_1, acc_2, acc_3, acc_4) as acc
from myTable

相关问题