如何用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。 我希望在特殊字符的所有缺失字符串中动态更改。请帮助我
答案 0 :(得分:0)
您需要正确的功能,这很容易解决。例如,在我的数据库中,我有:
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功能 - 您可以找到更多关于它们的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]);
答案 1 :(得分:0)
您可以尝试不创建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