【问题标题】:Sql remove duplicates from comma separated stringSql从逗号分隔的字符串中删除重复项
【发布时间】:2018-08-27 22:17:57
【问题描述】:

我想在 sql-server 中进行查询,它可以使以下输出像 column_A 中的列 _B 一样。列是 varchar 类型。

  Column_A                                 column_B
  karim,karim,rahim,masud,raju,raju        karim,rahim,masud,raju
  jon,man,jon,kamal,kamal                  jon,man,kamal
  c,abc,abc,pot                            c,abc,pot

【问题讨论】:

  • 永远不要将数据存储为逗号分隔的项目。只会给你带来很多麻烦。
  • 修复您的数据结构,使其与关系数据库更加兼容。那么重组会简单得多。
  • 为什么第一行的 rahim 必须在 B 列中丢弃?
  • 谢谢,我已经编辑了。
  • 该示例导致搜索:sql 从逗号分隔的字符串中删除重复项。第一页包含stackoverflow.com/questions/42918548/…stackoverflow.com/questions/20882509/…

标签: sql sql-server tsql split


【解决方案1】:

SQL 删除逗号分隔字符串中的重复项:

伪代码:创建一个 postgresql 函数,接收逗号分隔的字符串作为输入,并在内存中创建另一个数组。用逗号分割字符串,修剪空格并枚举每个项目,如果该项目未出现在新列表中,则添加它。最后将新数组展平为字符串并返回。

drop function if exists remove_duplicates_from_comma_separated_string(text);

CREATE or replace FUNCTION remove_duplicates_from_comma_separated_string(arg1 text) 
RETURNS text language plpgsql AS $$ declare 
  item text;  
  split_items text[];  
  ret_items text[];  
  ret_val text; 
BEGIN 
  --split your string on commas and trim whitespace 
  split_items := string_to_array(ltrim(arg1), ','); 
  --enumerate each item, if it doesn't exist in the new array then add it. 
  FOREACH item IN ARRAY split_items LOOP 
    if ( item::text = ANY(ret_items)) then 
    else 
        --append this unique item into ret_items 
        select array_append(ret_items, ltrim(item)) into ret_items; 
    end if;  
  END LOOP; 
  --flatten the final array to a text with comma delimiter 
  SELECT array_to_string(ret_items, ',', '*') into ret_val; 
  return ret_val; 
END; $$;

所以现在我们可以直接调用表格上的函数了:

drop table if exists foo_table; 
create table foo_table(name text); 
insert into foo_table values('karim,karim,rahim,masud,raju,raju'); 
insert into foo_table values('jon,man,jon,kamal,kamal'); 
insert into foo_table values('jon,man,kamal'); 
insert into foo_table values('c,abc,poty'); 
insert into foo_table values('c,abc,abc,kotb'); 
select remove_duplicates_from_comma_separated_string(name) from foo_table; 

哪些打印:

┌───────────────────────────────────────────────┐ 
│ remove_duplicates_from_comma_separated_string │ 
├───────────────────────────────────────────────┤ 
│ karim,rahim,masud,raju                        │ 
│ jon,man,kamal                                 │ 
│ jon,man,kamal                                 │ 
│ c,abc,poty                                    │ 
│ c,abc,kotb                                    │ 
└───────────────────────────────────────────────┘ 

代码异味 haaax 系数:9.5 / 10。施工人员看着新手程序员用 90 美元的 sql 品牌管扳手敲钉子,每个人都翻白眼。

【讨论】:

    【解决方案2】:

    首先:你已经在 cmets 中被告知,这是一个非常糟糕的设计(违反 1.NF)!如果您有一点机会改变这一点,您真的应该... 永远不要在一个单元格中存储多个值!

    如果你必须坚持这个(或为了修复这个烂摊子),你可以这样:

    这是我能想到的最简单的方法:将 CSV 转换为 XML 并调用 XQuery-function distinct-values()

    DECLARE @tbl TABLE(ColumnA VARCHAR(MAX));
    INSERT INTO @tbl VALUES
     ('karim,karim,rahim,masud,raju,raju')
    ,('jon,man,jon,kamal,kamal')
    ,('c,abc,abc,pot');
    
    WITH Splitted AS
    (
        SELECT ColumnA 
              ,CAST('<x>' + REPLACE(ColumnA,',','</x><x>') + '</x>' AS XML) AS TheParts
        FROM @tbl 
    )
    SELECT ColumnA
          ,TheParts.query('distinct-values(/x/text())').value('.','varchar(250)') AS ColumnB
    FROM Splitted;
    

    结果

    ColumnA                             ColumnB
    karim,karim,rahim,masud,raju,raju   karim rahim masud raju
    jon,man,jon,kamal,kamal             jon man kamal
    c,abc,abc,pot                       c abc pot
    

    更新 保留逗号

    WITH Splitted AS
    (
        SELECT ColumnA 
              ,CAST('<x>' + REPLACE(ColumnA,',','</x><x>') + '</x>' AS XML) AS TheParts
        FROM @tbl 
    )
    SELECT ColumnA
          ,STUFF(
              (TheParts.query
              ('
              for $x in distinct-values(/x/text())
                return <x>{concat(",", $x)}</x>
              ').value('.','varchar(250)')),1,1,'') AS ColumnB
    FROM Splitted;
    

    结果

    ColumnB
    karim,rahim,masud,raju
    jon,man,kamal
    c,abc,pot
    

    【讨论】:

    • 使用 REPLACE 来返回逗号不是更容易吗?像这样的东西? "REPLACE(TheParts.query('distinct-values(/x/text())').value('.','varchar(250)') , ' ' , ',') AS ColumnB" ?
    • @hkravitz 好吧,如果值可能包含空格,这会将逗号放在不好的地方...我经常希望有可能将分隔符传递给此类 XQuery 函数(与 @ 相同) 987654328@) 但是默认情况下这总是一个空白...
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 2012-01-30
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 2016-05-21
    相关资源
    最近更新 更多