删除特殊字符分隔字符串中的重复项和 NULL
Removing duplicates and NULL in Special character separated String
在开始我的问题之前,我肯定同意这是一个糟糕的设计,现在我们正在努力修复它。展望未来,对于所有新数据,我们将遵循 1NF
---Here is the fiddle----
我有一个这样的table数据。
我想删除重复的值和 'NULL' 个值。
预期输出:
180;;200
AMD;;SRD
ASE;;GIF;;TED
1
AMD;;SRD
null
LKG;;This is text with space
我试过的:
WITH Splitted AS
(
select id,attr,val
,CAST('<x>' + REPLACE(replace(val,'NULL',''),';;','</x><x>') + '</x>' AS XML) AS TheParts
from test where val like '%;;%'
)
SELECT
Replace(STUFF(
(TheParts.query
('
for $x in distinct-values(/x/text())
return <x>{concat(";;", $x)}</x>
').value('.','varchar(250)')),1,2,''),' ','') AS ColumnB
FROM Splitted;
当前输出
180;;200
AMD;;SRD
ASE;;GIF;;TED;;ASE --problem here
1
AMD;;SRD
null
LKG;;Thisistextwithspace -- problem here
我也在字符串之间丢失 space。在某些情况下,该值会重复。我想是因为最后有额外的 spaces。如何解决这个问题?或者有没有更好的方法来实现这个?
由于您使用的是旧版本的 SQL 服务器,因此您无法访问 STRING_SPLIT
或 STRING_AGG
。然而,前者在这里并不是特别有用,因为 Microsoft still 还没有在函数中实现序数位置,它只支持单个字符分离器.
我将改用 DelimitedSplit8k_LEAD
, 支持序数位置。不幸的是,它也只支持单个字符分隔符,所以我用竖线 (|
) 替换了双分号 (;;
) 分隔符;因为我认为这不会出现在您的数据中。
2012 也没有 TRIM
,因此您需要使用 RTRIM
和 LTRIM
来 trim 值。
最后可以使用"old"FOR XML PATH
方法"re-aggregate"字符串:
WITH Splits AS(
SELECT t.id,
t.attr,
DS.ItemNumber,
NULLIF(LTRIM(RTRIM(DS.Item)),'NULL') AS Item,
ROW_NUMBER() OVER (PARTITION BY T.id, LTRIM(RTRIM(NULLIF(DS.Item,'NULL'))) ORDER BY DS.ItemNumber) AS RN
FROM dbo.test t
CROSS APPLY dbo.DelimitedSplit8K_LEAD(REPLACE(t.val,';;','|'),'|') DS) --DelimitedSplit8K only supports a one character splitter
SELECT t.ID,
t.attr,
STUFF((SELECT ';;' + S.Item
FROM Splits S
WHERE S.ID = t.ID
AND S.RN = 1
ORDER BY S.ItemNumber
FOR XML PATH(''),TYPE).value('.','varchar(MAX)'),1,2,'') AS NewVal
FROM dbo.test t;
编辑:忘记了重复项。我在 CTE 中使用 ROW_NUMBER
对值进行编号,然后在 FOR XML PATH
子查询的 WHERE
中进行过滤。 DISTINCT
和 GROUP BY
不会在那里工作,因为 ItemNumber
将不允许在 ORDER BY
.
中使用
在开始我的问题之前,我肯定同意这是一个糟糕的设计,现在我们正在努力修复它。展望未来,对于所有新数据,我们将遵循 1NF
---Here is the fiddle----
我有一个这样的table数据。
我想删除重复的值和 'NULL' 个值。
预期输出:
180;;200
AMD;;SRD
ASE;;GIF;;TED
1
AMD;;SRD
null
LKG;;This is text with space
我试过的:
WITH Splitted AS
(
select id,attr,val
,CAST('<x>' + REPLACE(replace(val,'NULL',''),';;','</x><x>') + '</x>' AS XML) AS TheParts
from test where val like '%;;%'
)
SELECT
Replace(STUFF(
(TheParts.query
('
for $x in distinct-values(/x/text())
return <x>{concat(";;", $x)}</x>
').value('.','varchar(250)')),1,2,''),' ','') AS ColumnB
FROM Splitted;
当前输出
180;;200
AMD;;SRD
ASE;;GIF;;TED;;ASE --problem here
1
AMD;;SRD
null
LKG;;Thisistextwithspace -- problem here
我也在字符串之间丢失 space。在某些情况下,该值会重复。我想是因为最后有额外的 spaces。如何解决这个问题?或者有没有更好的方法来实现这个?
由于您使用的是旧版本的 SQL 服务器,因此您无法访问 STRING_SPLIT
或 STRING_AGG
。然而,前者在这里并不是特别有用,因为 Microsoft still 还没有在函数中实现序数位置,它只支持单个字符分离器.
我将改用 DelimitedSplit8k_LEAD
, 支持序数位置。不幸的是,它也只支持单个字符分隔符,所以我用竖线 (|
) 替换了双分号 (;;
) 分隔符;因为我认为这不会出现在您的数据中。
2012 也没有 TRIM
,因此您需要使用 RTRIM
和 LTRIM
来 trim 值。
最后可以使用"old"FOR XML PATH
方法"re-aggregate"字符串:
WITH Splits AS(
SELECT t.id,
t.attr,
DS.ItemNumber,
NULLIF(LTRIM(RTRIM(DS.Item)),'NULL') AS Item,
ROW_NUMBER() OVER (PARTITION BY T.id, LTRIM(RTRIM(NULLIF(DS.Item,'NULL'))) ORDER BY DS.ItemNumber) AS RN
FROM dbo.test t
CROSS APPLY dbo.DelimitedSplit8K_LEAD(REPLACE(t.val,';;','|'),'|') DS) --DelimitedSplit8K only supports a one character splitter
SELECT t.ID,
t.attr,
STUFF((SELECT ';;' + S.Item
FROM Splits S
WHERE S.ID = t.ID
AND S.RN = 1
ORDER BY S.ItemNumber
FOR XML PATH(''),TYPE).value('.','varchar(MAX)'),1,2,'') AS NewVal
FROM dbo.test t;
编辑:忘记了重复项。我在 CTE 中使用 ROW_NUMBER
对值进行编号,然后在 FOR XML PATH
子查询的 WHERE
中进行过滤。 DISTINCT
和 GROUP BY
不会在那里工作,因为 ItemNumber
将不允许在 ORDER BY
.