假设我有2个看起来像数组的变量:
declare @code nvarchar(200) =
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
declare @value nvarchar(200) =
'True~~100000006~Digital~0~0~~1388.76~Completed~True';
我需要查找@code
是否包含10490
(例如),如果包含,则需要在@value
变量中找到对应的值(按其索引) Digital
因为10490
是@code
数组中的第4个元素,而@value
数组中的第4个元素是Digital
(请注意{{1}的第2个元素}数组为NULL。
免责声明:
@value
数组将始终包含唯一值。例如,@code
不能超过1。
10490
数组将始终以','开头和结尾。
如果您从@code
变量中删除第一个和最后一个逗号,则@code
和@value
中的元素数将始终相同。
我无法使用函数或存储过程,因此一切都需要作为1个查询的一部分来完成。
答案 0 :(得分:1)
这里有两种可能。在您的情况下,我什至会尝试将其合并为一个WHILE
循环。
(兼容级别130及更高版本),您可以使用内置函数STRING_SPLIT
DECLARE @code nvarchar(200) =
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
DECLARE @value nvarchar(200) =
'True~~100000006~Digital~0~0~~1388.76~Completed~True';
DECLARE @valuetosearch nvarchar(200) = '10490'
SELECT value FROM
(
SELECT value ,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS 'idx'
FROM STRING_SPLIT ( @value , '~' )
) AS x2
WHERE x2.idx =
(
SELECT idx-1 FROM
(
SELECT value ,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS 'idx'
FROM STRING_SPLIT ( @code , ',' )
) AS x1
WHERE x1.[value] = @valuetosearch
)
DECLARE @code nvarchar(200) =
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
DECLARE @value nvarchar(200) =
'True~~100000006~Digital~0~0~~1388.76~Completed~True';
DECLARE @valuetosearch nvarchar(200) = '10490'
DECLARE @codetbl AS TABLE (idx int IDENTITY(1,1)
,code nvarchar(200))
DECLARE @valuetbl AS TABLE (idx int IDENTITY(1,1)
,value nvarchar(200))
DECLARE @name nvarchar(200)
DECLARE @pos int
WHILE CHARINDEX(',', @code) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @code)
SELECT @name = SUBSTRING(@code, 1, @pos-1)
INSERT INTO @codetbl
SELECT @name
SELECT @code = SUBSTRING(@code, @pos+1, LEN(@code)-@pos)
END
INSERT INTO @codetbl
SELECT @code
WHILE CHARINDEX('~', @value) > 0
BEGIN
SELECT @pos = CHARINDEX('~', @value)
SELECT @name = SUBSTRING(@value, 1, @pos-1)
INSERT INTO @valuetbl
SELECT @name
SELECT @value = SUBSTRING(@value, @pos+1, LEN(@value)-@pos)
END
INSERT INTO @valuetbl
SELECT @value
SELECT value FROM @valuetbl
WHERE idx = (SELECT idx-1 FROM @codetbl WHERE code = @valuetosearch)
答案 1 :(得分:1)
当找不到@tofind时,您可能需要添加一些代码
declare @code nvarchar(200) =
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
declare @value nvarchar(200) =
'True~~100000006~Digital~0~0~~1388.76~Completed~True';
declare @tofind nvarchar(200) = '10490';
--select left(@code,CHARINDEX(@tofind,@code))
--select len(left(@code,CHARINDEX(@tofind,@code))) - LEN( REPLACE( left(@code,CHARINDEX(@tofind,@code)) , ',', ''))
declare @nth int;
set @nth = len(left(@code,CHARINDEX(@tofind,@code))) - LEN( REPLACE( left(@code,CHARINDEX(@tofind,@code)) , ',', ''))
declare @SplitOn nvarchar = '~';
declare @RowData nvarchar(200) = @value + '~';
declare @Cnt int = 1
While (Charindex(@SplitOn,@RowData)>0) and @Cnt < @nth
Begin
Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
Set @Cnt = @Cnt + 1
End
Select --Data = ltrim(rtrim(@RowData)),
Case when ltrim(rtrim(@RowData)) = '' then null else
LEFT(ltrim(rtrim(@RowData)) , CHARINDEX('~',ltrim(rtrim(@RowData))) -1)
end as Result
答案 2 :(得分:1)
我想您知道,这是一个非常糟糕的设计...如果您可以更改它,那么您应该这样做。但这可以解决:
declare @code nvarchar(200) =
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
declare @value nvarchar(200) =
'True~~100000006~Digital~0~0~~1388.76~Completed~True';
-查询会将两个字符串都转换为可拆分的XML
-query('/x[text()]')
将删除空条目(前导和尾随逗号)
-(...假设@code
中永远不会有空条目)
-然后它将从两者读取派生的编号列表
-最终它将两个列表都加入他们的PartIndex
WITH Casted AS
(
SELECT CAST('<x>' + REPLACE(@code,',','</x><x>') + '</x>' AS XML).query('/x[text()]') AS CodeXml
,CAST('<x>' + REPLACE(@value,'~','</x><x>') + '</x>' AS XML) AS ValueXml
)
,CodeDerived AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PartIndex
,x.value('text()[1]','nvarchar(max)') AS CodePart
FROM Casted
CROSS APPLY CodeXml.nodes('/x') A(x)
)
,ValueDerived AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PartIndex
,x.value('text()[1]','nvarchar(max)') AS ValuePart
FROM Casted
CROSS APPLY ValueXml.nodes('/x') A(x)
)
SELECT cd.PartIndex
,CodePart
,ValuePart
FROM CodeDerived cd
INNER JOIN ValueDerived vd ON cd.PartIndex=vd.PartIndex
结果
inx CodePart ValuePart
1 10501 True
2 10203 NULL
3 10491 100000006
4 10490 Digital
5 10091 0
6 10253 0
7 10008 NULL
8 10020 1388.76
9 10570 Completed
10 10499 True
只需添加一个简单的WHERE
即可将其减小为所需的一个值。
免责声明:不能保证使用ROW_NUMBER
和ORDER BY (SELECT NULL)
进行的编号将返回正确的顺序,但是更好的机会是您需要SQL Server 2016+。 For more details: read this link and the other contributions there
答案 3 :(得分:0)
这应该很简单。如果性能很重要,我建议使用DelimitedSplit8K分割字符串。这是一个简单的高性能解决方案:
np.savez('test.npz',format(list(a.keys())[0])=list(a.values())[0])
结果:
SyntaxError: keyword can't be an expression