通过删除重复项且无需逐行处理对两个 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*
我正在尝试合并两个 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*