为 CSV 字符串中的重复值添加编号

问题描述 投票:0回答:2

我在 T-SQL 中有一个像这样的 CSV 字符串:

@csv = 'a,f,d,f,b,b,f'

如何使该字符串仅包含这样的唯一值:

@csv =  'a,f,d,f_1,b,b_2,f_2'
sql sql-server t-sql
2个回答
0
投票

根据我的理解,所有其他事件都包含“_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;


0
投票

请尝试以下基于通过 SQL Server 的 XML 和 XQuery 功能进行标记化的解决方案。

值得注意的点:

  • CROSS APPLY
    正在将 csv 字符串转换为 XML 数据类型。
  • XQuery FLWOR表达式正在遍历XML,并计算(1) 令牌在序列中的位置,以及 (2) 令牌的计数器 值达到该位置。
  • XQuery
    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
© www.soinside.com 2019 - 2024. All rights reserved.