如何替换在sql中具有相同位置的其他列值的特殊字符?
问题描述:
如何替换特殊字符之间的缺少字符串与其他列相同位置特殊字符字符串在SQL中?下面是例子如何替换在sql中具有相同位置的其他列值的特殊字符?
如:
ColumnA columnB Output of columnb
~as~df~gf~er ~qw~~~ ~qw~df~gf~er
~Evening~Afternoon ~~ ~Evening~Afternoon
~qw~dg~er~rt~yu~io~ty ~df~~rt~~we~~ ~df~dg~rt~rt~we~io~ty
提示:这列特殊字符数将是相同的。 我需要这样的列输出〜qw〜df〜gf〜er。
我想动态改变所有缺少特殊字符的字符串。请在此帮助我
答
您需要正确的功能,并且可以轻松解决。例如,在我的数据库,我有:
DECLARE @DataSource TABLE
(
[ColumnA] VARCHAR(1024)
,[ColumnB] VARCHAR(1024)
);
INSERT INTO @DataSource ([ColumnA], [ColumnB])
VALUES ('~as~df~gf~er', '~qw~~~')
,('~Evening~Afternoon', '~~')
,('~qw~dg~er~rt~yu~io~ty', '~df~~rt~~we~~');
SELECT DS.[ColumnA]
,DS.[ColumnB]
,[dbo].[ConcatenateWithOrderAndDelimiter] (A.[index], ISNULL(NULLIF(B.[value], ''), A.[value]), '~')
FROM @DataSource DS
CROSS APPLY [dbo].[fn_Utils_RegexSplitWithOrder] ([ColumnA], '~') A
LEFT JOIN
(
SELECT [ColumnA]
,B.[index]
,B.[value]
FROM @DataSource DS
CROSS APPLY [dbo].[fn_Utils_RegexSplitWithOrder] ([ColumnB], '~') B
) B
ON DS.[ColumnA] = B.[ColumnA]
AND A.[index] = B.[index]
GROUP BY DS.[ColumnA]
,DS.[ColumnB];
所以,基本上需要两个功能:
- 一个由价值
- 一个分割字符串字符串聚集(串联)
在我的情况我使用SQL CLR的乐趣ction - 你可以找到更多关于他们here。
在SQL Server 2017中,我们可以使用STRING_AGG,而从SQL Server 2016我们可以使用STRING_SPIT。
如果你不想浪费时间来实现SQL CLR函数,你可以添加一个拆分函数(网络中有很多)。例如,我用这一个:
CREATE FUNCTION [dbo].[fn_Analysis_ConvertCsvListToNVarCharTableWithOrder](@List nvarchar(max), @Delimiter nvarchar(10) = ',')
RETURNS @result TABLE
(
[Value] nvarchar(max),
[SortOrder] bigint NOT NULL
)
AS
BEGIN
IF @Delimiter is null
BEGIN
SET @Delimiter = ','
END
DECLARE @XML xml = N'<r><![CDATA[' + REPLACE(@List, @Delimiter, ']]></r><r><![CDATA[') + ']]></r>'
DECLARE @BufTable TABLE (Value nvarchar(max), SortOrder bigint NOT NULL IDENTITY(1, 1) PRIMARY KEY)
INSERT INTO @BufTable (Value)
SELECT Tbl.Col.value('.', 'nvarchar(max)')
FROM @xml.nodes('//r') Tbl(Col)
OPTION (OPTIMIZE FOR (@xml = NULL))
INSERT INTO @result (Value, SortOrder)
SELECT Value, SortOrder
FROM @BufTable
RETURN
END
,这应该会给你想你想:
WITH DataSource AS
(
SELECT DS.[ColumnA]
,DS.[ColumnB]
,A.[SortOrder]
,ISNULL(NULLIF(B.[value], ''), A.[Value]) AS [Value]
FROM @DataSource DS
CROSS APPLY [dbo].[fn_Analysis_ConvertCsvListToNVarCharTableWithOrder] (REPLACE([ColumnA], ',', '~'), '~') A
LEFT JOIN
(
SELECT [ColumnA]
,B.[SortOrder]
,B.[value]
FROM @DataSource DS
CROSS APPLY [dbo].[fn_Analysis_ConvertCsvListToNVarCharTableWithOrder] (REPLACE([ColumnB], ',', '~'), '~') B
) B
ON DS.[ColumnA] = B.[ColumnA]
AND A.[SortOrder] = B.[SortOrder]
)
SELECT DISTINCT A.[ColumnA]
,A.[ColumnB]
,DS.[value]
FROM DataSource A
CROSS APPLY
(
SELECT STUFF
(
(
SELECT '~' + B.[Value]
FROM DataSource B
WHERE A.[ColumnA] = B.[ColumnA]
ORDER BY B.[SortOrder]
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1
,1
,''
)
) DS ([value]);
答
你可以尝试,而无需创建Function()
: -
DECLARE @ColumnA NVARCHAR(MAX);
DECLARE @columnB NVARCHAR(MAX);
SET @ColumnA = '~as~df~gf~er ';
SET @columnB = ' ~qw~~~';
;WITH CTE
AS (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA,
ROW_NUMBER() OVER(ORDER BY @ColumnA) RN
FROM
(
SELECT CAST('<M>'+REPLACE(@ColumnA, '~', '</M><M>')+'</M>' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/M') AS Split(a)),
CTE1
AS (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA1,
ROW_NUMBER() OVER(ORDER BY @columnB) RN
FROM
(
SELECT CAST('<M>'+REPLACE(@columnB, '~', '</M><M>')+'</M>' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/M') AS Split(a))
SELECT @ColumnA AS ColumnA,
@columnB AS columnB,
[Output of columnb] =
(
SELECT '~'+CASE
WHEN C1.DATA1 = ''
THEN C2.DATA
ELSE C1.DATA1
END
FROM CTE1 C1
INNER JOIN CTE C2 ON C2.RN = C1.RN
AND C1.RN > 1 FOR XML PATH('')
);
期望输出:
ColumnA columnB Output of columnb
~as~df~gf~er ~qw~~~ ~qw~df~gf~er
这是你的更新规则,这很不清楚吗? –
在哪个位置数据应该被替换或更新? –
如果在特殊字符之间缺少字符串,我们需要将columnA字符串替换为相同的位置。而columnb需要更新columnb(这是我需要在columnb中更新的方式) – Malyadri