通过删除重复项并且不进行逐行处理来对两个csv字段进行排序

时间:2018-02-21 07:01:42

标签: tsql sql-server-2008-r2

我正在尝试组合两个csv字段,消除重复,排序并将其存储在新字段中。

我能够做到这一点。但是,我遇到的情况是值类似于abc和abc *。我需要用abc *保留一个并删除另一个。 这可以在没有逐行处理的情况下实现吗?

这就是我所拥有的。

CREATE TABLE csv_test
    (
        Col1 VARCHAR(100),
        Col2 VARCHAR(100),
        Col3 VARCHAR(500)
    );

INSERT dbo.csv_test (Col1, Col2)
VALUES ('xyz,def,abc', 'abc*,tuv,def,xyz*,abc'), ('qwe,bca,a23', 'qwe,bca,a23*,abc')
--It is assumed that there are no spaces around commas

SELECT Col1, Col2, Col1 + ',' + Col2 AS Combined_NonUnique_Unsorted, 
STUFF((
                 SELECT  ',' + Item
                 FROM     (SELECT DISTINCT Item FROM dbo.DelimitedSplit8K(Col1 + ',' + Col2,',')) t
                 ORDER BY Item
                 FOR XML PATH('')
             ),1,1,'') Combined_Unique_Sorted
, ExpectedResult = 'Keep the one with * and make it unique'
FROM   dbo.csv_test;

--Expected Results; if there are values like abc and abc* ; I need to keep abc* and remove abc ; 
--How can I achieve this without looping or using temp tables?

abc,abc*,def,tuv,xyz,xyz*   ->  abc*,def,tuv,xyz*
a23,a23*,abc,bca,qwe        ->  a23*,abc,bca,qwe

1 个答案:

答案 0 :(得分:1)

好吧,既然你同意将数据库规范化是正确的事情,我决定尝试为你提出一个解决方案。
我最终得到了一个非常繁琐的解决方案,涉及4个(!)公用表表达式 - 繁琐,但它的工作原理。

第一个 cte是添加表格中缺少的行标识符 - 我已经使用了ROW_NUMBER() OVER(ORDER BY Col1, Col2)
second cte是通过组合两个csv列来获取一组唯一值。请注意,这还没有处理*部分 第三个 cte正在处理*问题 最后,第四个 cte将所有独特的项目放回到单个csv中。 (我可以在第三个cte中完成它,但我想让每个cte负责解决方案的一个部分 - 它更具可读性。)

现在剩下的就是用第四个cte的Col3来更新第一个cte的Combined_Unique_Sorted

;WITH cte1 as
(
    SELECT  Col1, 
            Col2, 
            Col3,
            ROW_NUMBER() OVER(ORDER BY Col1, Col2) As rn
    FROM dbo.csv_test
), cte2 as
(
    SELECT rn, Item
    FROM cte1
    CROSS APPLY 
    (
        SELECT DISTINCT Item 
        FROM dbo.DelimitedSplit8K(Col1 +','+ Col2, ',') 
    ) x
), cte3 AS
(
    SELECT rn, Item
    FROM cte2 t0
    WHERE NOT EXISTS
    (
        SELECT 1
        FROM cte2 t1
        WHERE t0.Item + '*' = t1.Item
        AND t0.rn = t1.rn
    )
), cte4 AS
(
    SELECT rn, 
           STUFF
           ((
             SELECT  ',' + Item
             FROM cte3 t1
             WHERE t1.rn = t0.rn
             ORDER BY Item
             FOR XML PATH('')
           ), 1, 1, '') Combined_Unique_Sorted
    FROM cte3 t0
)

UPDATE t0
SET Col3 = Combined_Unique_Sorted
FROM cte1 t0
INNER JOIN cte4 t1 ON t0.rn = t1.rn

验证结果:

SELECT *
FROM csv_test
ORDER BY Col1, Col2

结果:

Col1            Col2                    Col3
qwe,bca,a23     qwe,bca,a23*,abc        a23*,abc,bca,qwe
xyz,def,abc     abc*,tuv,def,xyz*,abc   abc*,def,tuv,xyz*

You can see a live demo on rextester.