我在 T-SQL 中有一个像这样的 CSV 字符串:
@csv = 'a,f,d,f,b,b,f'
如何使该字符串仅包含这样的唯一值:
@csv = 'a,f,d,f_1,b,b_2,f_2'
根据我的理解,所有其他事件都包含“_X”。这对于 SQL 来说是 100% 可能的。
我将创建一个 CTE 并使用 ROW_NUMBER()。从那里开始,连接每个大于 1 的值。
WITH CTE AS (
SELECT
list,
ROW_NUMBER() OVER (PARTITION BY list ORDER BY list) AS [Index]
FROM Table)
SELECT
CASE WHEN [Index] > 1 THEN CONCAT(list, '_', [Index]) ELSE list END AS 'New_list'
FROM CTE;
请尝试以下基于通过 SQL Server 的 XML 和 XQuery 功能进行标记化的解决方案。
值得注意的点:
CROSS APPLY
正在将 csv 字符串转换为 XML 数据类型。return if ... then ... else
语句决定是否连接“_”和令牌计数器。SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (id INT IDENTITY PRIMARY KEY, csv VARCHAR(1024));
INSERT INTO @tbl (csv) VALUES
('a,f,d,f,b,b,f');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = ',';
SELECT *
, REPLACE(x.query('
for $x in /root/r
let $pos := count(root/r[. << $x]) + 1
let $counter := count(/root/r[position() le $pos and text()=data($x)])
return if ($counter gt 1) then concat(data($x), "_", string($counter - 1))
else data($x)
').value('.', 'VARCHAR(1024)'), SPACE(1), @separator) AS result
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(csv, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(x);
输出
id | csv | 结果 |
---|---|---|
1 | a,f,d,f,b,b,f | a,f,d,f_1,b,b_1,f_2 |