我有这样的刺痛
,x,x,y,x,x,O,x,y
与此值匹配的其他字符串中的值
0〜1〜b ~~ z〜XY〜1〜7。
值“ O”可以切换其在字符串中的位置,其他字符串中的值也可以。
值“ O”位于第6位,因此预期结果将为“ XY”。
第一个字符串始终在每个值之前以“,”开头。第二个字符串首先以值开头,后跟“〜”。
“ O”是不会改变的给定值,因此我总是必须在第二个字符串中找到“ O”所在位置的给定值。
这就是我要介绍的内容:
,x,x,y,x,x,O,x,y
0〜1〜b ~~ z〜XY〜1〜7
O = XY
,x,O,y,x,x,y,x,y
0〜1〜b ~~ z〜XY〜1〜7
O = 1
谢谢。
答案 0 :(得分:1)
获取DelimitedSplit8K的副本,然后您可以执行以下操作:
DECLARE @string1 VARCHAR(1000) = ',x,x,y,x,x,O,x,y',
@string2 VARCHAR(1000) = '0~1~b~~z~XY~1~7';
DECLARE @search VARCHAR(1000) = 'O'; -- best as a variable/parameter
SELECT *
FROM dbo.delimitedSplit8K(@string2,'~') AS s
WHERE s.itemNumber =
(
SELECT TOP (1) s2.itemNumber -- TOP (1) until we know about dupicates
FROM dbo.delimitedSplit8K(@string1,',') AS s2
WHERE s2.item = @search
)-1;
返回:
ItemNumber Item
-------------------- -------
6 XY
答案 1 :(得分:1)
这是基于JSON的解决方案:
编辑:最快的方法(需要v2016)->删除了基于XQuery的解决方案
DECLARE @string1 VARCHAR(1000) = ',x,x,x,x,x,O,x,y',
@string2 VARCHAR(1000) = '0~1~b~~z~XY~1~7';
SELECT s2.[value]
FROM OPENJSON('["' + REPLACE(@string1,',','","') + '"]') AS s1
CROSS APPLY OPENJSON('["' + REPLACE(@string2,'~','","') + '"]') AS s2
WHERE s1.[value]='O' AND s2.[key]=s1.[key]-1;
简而言之:通过替换定界符,我们可以在JSON数组中转换定界的字符串,并使用JSON的功能来查找元素的位置,并使用此位置来获取另一个元素。
我进行了一些性能测试,发现XQuery解决方案的性能很差。使用最多10个元素的小字符串是可以的,但是如果使用较长的字符串(使用100个元素进行测试),则执行起来会很慢...
测试代码(如果有兴趣的话):
DECLARE @i INT=1
,@CountElements INT=5 --Use higher values here
,@CountRows INT=500;
DECLARE @tbl TABLE(ID INT IDENTITY, i1t90 INT, s1 VARCHAR(500),s2 VARCHAR(500));
DECLARE @TemplateString VARCHAR(1000);
WHILE @i<@CountElements
BEGIN
SET @TemplateString = CONCAT(@TemplateString,@i,'~');
SET @i=@i+1;
END
SET @i=1;
WHILE @i<@CountRows
BEGIN
INSERT INTO @tbl(i1t90, s1,s2)
SELECT
ISNULL(NULLIF(@i%@CountElements,0),@CountElements)
,STUFF(REPLICATE(',x',@CountElements),(ISNULL(NULLIF(@i%@CountElements,0),@CountElements))*2,1,'O')
,CONCAT(@TemplateString,@i)
SET @i=@i+1;
END
DECLARE @d DATETIME2=SYSUTCDATETIME();
SELECT t.*
,B.PosO
,A.y.value('(/y[sql:column("B.PosO")]/text())[1]','nvarchar(100)') AS FoundValue
INTO #t1
FROM @tbl t
CROSS APPLY
(
SELECT (SELECT CAST('<x>' + REPLACE(s1,',','</x><x>') + '</x>' AS XML))
,(SELECT CAST('<y>' + REPLACE(s2,'~','</y><y>') + '</y>' AS XML))) AS A(x,y)
CROSS APPLY(SELECT A.x.value('count(/x[. << (/x[text()="O"])[1]])','int')) B(PosO);
SELECT 'XML based new', DATEDIFF(MILLISECOND,@d,SYSUTCDATETIME());
SET @d=SYSUTCDATETIME();
SELECT *
INTO #t2
FROM @tbl
CROSS APPLY dbo.delimitedSplit8K(s2,'~') AS s
WHERE s.itemNumber =
(
SELECT TOP (1) s1.itemNumber -- TOP (1) until we know about dupicates
FROM dbo.delimitedSplit8K(s1,',') AS s1
WHERE s1.item = 'O'
)-1;
SELECT 'Splitter based',DATEDIFF(MILLISECOND,@d,SYSUTCDATETIME());
SELECT * FROM #t1;
SELECT * FROM #t2;
DROP TABLE #t1;
DROP TABLE #t2;
在我的测试中,基于拆分器的方法快了大约八倍...
此方法比基于拆分器的方法快约5倍:
SELECT t.*
,s2.[key] +1 AS PosO --zero based index
,s2.[value] AS FoundValue
INTO #t3
FROM @tbl t
CROSS APPLY OPENJSON('["' + REPLACE(s1,',','","') + '"]') AS s1
CROSS APPLY OPENJSON('["' + REPLACE(s2,'~','","') + '"]') AS s2
WHERE s1.[value]='O' AND s2.[key]=s1.[key]-1;