我试图将逗号分隔的ID列表转换为以逗号分隔的前缀列表。
BKR394859607,MTP293840284,SPN489620586
我的目标是将SQL Server中IDString中的这3个ID转换为
BKR,MTP,SPN
此字符串可以包含无限数量的ID
Declare @ActivityID as varchar(MAX) = 'BKR394859607,MTP293840284,SPN489620586'
Declare @ActivityPrefixes as varchar(MAX)
Set @ActivityPrefixes = (function to Convert to comma delimited prefix list)
答案 0 :(得分:2)
如Sean Lange的评论所述,您需要执行三个步骤
像这样的东西
DECLARE @ActivityID AS VARCHAR(max) =
'BKR394859607,MTP293840284,SPN489620586,GHY489620586'
SELECT Stuff(split_val, 1, 1, '') as Result
FROM (SELECT ','
+ LEFT(split.a.value('.', 'VARCHAR(100)'), 3)
FROM (SELECT Cast ('<M>' + Replace(@ActivityID, ',', '</M><M>')
+ '</M>' AS XML) AS Data) AS A
CROSS apply data.nodes ('/M') AS Split(a)
FOR xml path(''))a(split_val)
结果: BKR,MTP,SPN,GHY
答案 1 :(得分:1)
试试这个:
DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR394859607,MTP293840284,SPN489620586';
DECLARE @ActivityPrefixes AS VARCHAR(MAX);
SET @ActivityPrefixes = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(
@ActivityID,'0', ''), '1',''), '2', ''),'3', ''), '4',''), '5', ''),
'6', ''),'7', ''), '8', ''), '9', '');
SELECT @ActivityPrefixes
如果你想获得每个部分的前3个字符,那么试试这个:
DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR39A859607,M3TP293840284,SP1N4896GG586,BKR394859607,MTP293840284,SPN489620586';
DECLARE @ActivityPrefixes AS VARCHAR(MAX);
SET @ActivityPrefixes = '';
WHILE 1 = 1
BEGIN
DECLARE @i INT;
IF CHARINDEX(',', @ActivityID) = 0
SET @i = 3;
ELSE
SET @i = CHARINDEX(',', @ActivityID) - 1;
IF @ActivityPrefixes = ''
SET @ActivityPrefixes = SUBSTRING(SUBSTRING(@ActivityID, 1, @i), 1,3);
ELSE
SET @ActivityPrefixes = @ActivityPrefixes + ','
+ SUBSTRING(SUBSTRING(@ActivityID, 1, @i), 1, 3);
IF CHARINDEX(',', @ActivityID) = 0
BREAK;
SET @ActivityID = SUBSTRING(@ActivityID,CHARINDEX(',', @ActivityID) + 1,LEN(@ActivityID));
END;
SELECT @ActivityPrefixes;
答案 2 :(得分:1)
首先,阅读以下文章,他们讨论拆分字符串(以及不这样做的理由),并比较方法的性能,如果你无法避免它。
这三篇文章的结果是(如果链接已经死亡):
最通用的方法是最后一种方法,因为不是每个人都可以使用CLR,并且保证没有特殊的XML字符,因此分割方法是:
CREATE FUNCTION [dbo].[Split]
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
( WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1), (1)) n (N)),
N2(N) AS (SELECT 1 FROM N1 a CROSS JOIN N1 b),
N3(N) AS (SELECT 1 FROM N2 a CROSS JOIN N2 b),
N4(N) AS (SELECT 1 FROM N3 a CROSS JOIN N3 b),
cteTally(N) AS
( SELECT 0 UNION ALL
SELECT TOP (DATALENGTH(ISNULL(@List,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM n4
),
cteStart(N1) AS
( SELECT t.N+1
FROM cteTally t
WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0)
)
SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000)),
Position = s.N1,
ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1)
FROM cteStart s
);
现在你有了Split函数,你可以拆分你的第一个字符串:
DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR394859607,MTP293840284,SPN489620586';
SELECT Item,
NewID = LEFT(Item, 3)
FROM dbo.Split(@ActivityID, ',');
这给了你:
Item NewID
-----------------------------
BKR394859607 BKR
MTP293840284 MTP
SPN489620586 SPN
然后,您可以使用FOR XML PATH()
:
DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR394859607,MTP293840284,SPN489620586';
SELECT STUFF(( SELECT ',' + LEFT(Item, 3)
FROM dbo.Split(@ActivityID, ',')
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '');
有关其工作原理的详情,请参阅this answer。
最佳解决方案可能是使用用户定义的表类型来存储字符串列表:
CREATE TYPE dbo.StringList AS TABLE (Value VARCHAR(MAX));
然后,不是建立一个分隔的字符串,而是建立一个表:
DECLARE @Activity dbo.StringList;
INSERT @Activity (Value)
VALUES ('BKR394859607'), ('MTP293840284'), ('SPN489620586');
然后你可以避免痛苦的分裂,并且可以很容易地操纵每个单独的记录。
如果你确实需要获得一个新的分隔字符串,那么你可以使用与上面相同的逻辑:
DECLARE @Activity dbo.StringList;
INSERT @Activity (Value)
VALUES ('BKR394859607'), ('MTP293840284'), ('SPN489620586');
SELECT STUFF(( SELECT ',' + LEFT(Value, 3)
FROM @Activity
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '');
答案 3 :(得分:1)
使用以下answer在regeular
中实现T-SQL
表达式函数。然后您可以使用以下内容: