【问题标题】:get all distinct values from a particular column with comma separated values从具有逗号分隔值的特定列中获取所有不同的值
【发布时间】:2019-02-05 01:36:23
【问题描述】:

我正在创建一个 sql 查询。我在stackoverflow中尝试了多个链接并用谷歌搜索,但不喜欢解决方案。我有以下内容:

column_name
1,2,3,string1
3,1,string2
4,5,string3
2,4,string1

所以我想要以下输出:

1,2,3,4,5,string1,string2,string3,string4

基本上我想从逗号分隔的列中获取所有唯一值。我知道与列中的每一行相比, distinct 给出不同的值,但是在上述情况下我们如何做到这一点。

注意:我使用的是 Oracle 11g 数据库。 Kaushik 的答案在 SQL Fiddler 中看起来不错。但它对我不起作用,因为我有超过 20k 行。有没有其他选择 ?

【问题讨论】:

  • 我删除了不兼容的数据库标签。请仅使用您真正使用的数据库进行标记。
  • 谢谢@GordonLinoff
  • @a_horse_with_no_name Oracle 11g。将在问题中更新。
  • 逗号分隔的项目。会给你带来很多麻烦...
  • 它们总是数字还是可以是字符串?

标签: sql oracle oracle11g


【解决方案1】:

使用传统方法将单个字符串拆分为不同的行,然后进行连接。唯一的问题是连接的字符串不应超过 4000 个字符

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE yourtable
    (column_name varchar2(13))
;

INSERT ALL 
    INTO yourtable (column_name)
         VALUES ('1,2,3,string1')
    INTO yourtable (column_name)
         VALUES ('3,1,string2')
    INTO yourtable (column_name)
         VALUES ('4,5,string3')
    INTO yourtable (column_name)
         VALUES ('2,4,string1')
SELECT * FROM dual
;

查询 1

select LISTAGG(val,',') WITHIN GROUP ( ORDER BY val ) as final
FROM
(
select distinct  trim(regexp_substr(column_name,'[^,]+', 1, level) ) as val 
  from yourtable
   connect by regexp_substr(column_name, '[^,]+', 1, level) is not null
  ORDER BY val
 )

Results

|                             FINAL |
|-----------------------------------|
| 1,2,3,4,5,string1,string2,string3 |

【讨论】:

  • 这正是我想要的,但由于我有更多结果(超过 19k 个结果),我认为它花费了太多时间。有没有其他更快的解决方案? @Kaushik Nayak
  • @test Account :更好的解决方案是更改表/模式设计并将值存储为具有适当键的行,遵循规范化规则。
【解决方案2】:

您可以使用regexp_replace 删除重复项并将结果与​​listagg 连接

SELECT 
       RTRIM(
         REGEXP_REPLACE(
           (listagg(Num,',') WITHIN GROUP (ORDER BY Num) OVER ()), 
           '([^,]*)(,\1)+($|,)', 
           '\1'),
         ',') Nums 
FROM Table;

【讨论】:

    【解决方案3】:

    已回复this question

    create table ##Testdata(SomeID int, OtherId varchar(100), Data varchar(max))
    insert ##Testdata select 1, '1,2,3', '1,2,3'
    insert ##Testdata select 2, '3,1', '3,1'
    insert ##Testdata select 3, '4,5', '4,5'
    insert ##Testdata select 4, '2,4', '2,4'
    
    ;with tmp(SomeID, OtherID, DataItem, Data) as (
    select SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
        STUFF(Data, 1, CHARINDEX(',',Data+','), '')
    from ##Testdata
    union all
    select SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
        STUFF(Data, 1, CHARINDEX(',',Data+','), '')
    from tmp
    where Data > ''
    )
    select SomeID, OtherID, DataItem
    from tmp
    order by SomeID
    -- OPTION (maxrecursion 0)
    -- normally recursion is limited to 100. If you know you have very long
    -- strings, uncomment the option
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 2014-11-20
    相关资源
    最近更新 更多