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

Sort two csv fields by removing duplicates and without row-by-row processing

我正在尝试合并两个 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

好吧,既然你同意规范化数据库是正确的做法,我决定尝试为你想出一个解决方案。
我最终得到了一个相当麻烦的解决方案,涉及 4(!) 个常见的 table 表达式 - 很麻烦,但它有效。

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

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

;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.