从逗号分隔的字符串中删除重复项的SQL语句

5
我希望在SQL Server中进行查询,使得输出结果的格式与列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

3
永远不要将数据存储为逗号分隔的项目。这样做只会给你带来很多麻烦。 - jarlh
2
将您的数据结构修正为更符合关系型数据库的标准,这样重组过程就会变得更加简单。 - Gordon Linoff
1
为什么在第一行中,B列必须舍弃Rahim? - Joe Taras
谢谢,我已经编辑过了。 - Biddut
1
该示例引导搜索:sql从逗号分隔的字符串中删除重复项。第一页包括 https://stackoverflow.com/questions/42918548/remove-duplicates-from-comma-or-pipeline-operator-string 和 https://stackoverflow.com/questions/20882509/sql-server-2000-remove-duplicates-from-comma-separated-string。 - Dan D.
2个回答

6
首先,评论中已经告诉你了,这是一个非常糟糕的设计(违反了第一范式)!如果您有最小的机会更改它,您真的应该……永远不要在一个单元格内存储多个值! 如果您必须坚持这种方式(或为了修复这个问题),您可以按如下方式操作:
这是我能想到的最简单的方法:将CSV转换为XML并调用XQuery函数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
@hkravitz 如果值可能包含空格,那么这将在错误的位置放置逗号... 我经常希望能够向这些 XQuery 函数(以及 data())传递分隔符的可能性。但默认情况下始终为空格... - Shnugo

0

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                                    │ 
└───────────────────────────────────────────────┘ 

代码异味哈克斯因子:9.5/10。建筑队员看着新手程序员用90美元的SQL品牌管钳敲钉子,大家都翻了个白眼。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接