Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays SQL-从数组中获取特定元素_Arrays_Sql Server_Tsql_Sql Server 2014 - Fatal编程技术网

Arrays SQL-从数组中获取特定元素

Arrays SQL-从数组中获取特定元素,arrays,sql-server,tsql,sql-server-2014,Arrays,Sql Server,Tsql,Sql Server 2014,假设我有两个看起来像数组的变量: 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(例如),如果包含,我需要找到相应的值(通过其索引)在@va

假设我有两个看起来像数组的变量:

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
变量中,该变量将是
数字的
,因为
10490
@code
数组的第四个元素,
@value
数组的第四个元素是
数字的
(请注意,
@value
数组的第二个元素为空)

免责声明
@code
数组将始终包含唯一的值。例如,不可能有超过1个
10490
@code
数组始终以“,”开头和结尾。 如果从
@code
变量中去掉第一个和最后一个逗号,则
@code
@value
中的元素数将始终相同。
我无法使用函数或存储过程,因此所有操作都需要作为1个查询的一部分来完成。

这里有两种可能性。在您的情况下,我甚至会尝试在循环时将其合并为一个

SQL Server 2016及以上版本 (兼容级别130及以上)您可以使用内置函数
STRING\u 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
)
对于早期版本的SQL Server:
当找不到@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
declare@code-nvarchar(200)=
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
声明@value nvarchar(200)=
'True~~10000006~数字~0~0~~1388.76~已完成~True';
声明@tofind nvarchar(200)='10490';
--选择左侧(@code,CHARINDEX(@tofind,@code))
--选择len(左(@code,CHARINDEX(@tofind,@code)))-len(替换(左(@code,CHARINDEX(@tofind,@code)),',','')
声明@nth int;
设置@nth=len(左(@code,CHARINDEX(@tofind,@code)))-len(替换(左(@code,CHARINDEX(@tofind,@code)),',','')
声明@SplitOn nvarchar='~';
声明@rowdatanvarchar(200)=@value+'~';
声明@Cnt int=1
而(Charindex(@SplitOn,@RowData)>0)和@Cnt<@nth
开始
设置@RowData=Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
设置@Cnt=@Cnt+1
终点
选择--Data=ltrim(rtrim(@RowData)),
当ltrim(rtrim(@RowData))=''然后为null else时的情况
左(ltrim(rtrim(@RowData)),CHARINDEX(“~”,ltrim(rtrim(@RowData)))-1)
结果

我想你知道,这是一个非常糟糕的设计……如果你能改变这一点,你真的应该改变。但这是可以解决的:

declare@code-nvarchar(200)=
',10501,10203,10491,10490,10091,10253,10008,10020,10570,10499,';
声明@value nvarchar(200)=
'True~~10000006~数字~0~0~~1388.76~已完成~True';
--查询将两个字符串转换为可拆分的XML
--
查询('/x[text()]')
将删除空条目(前导和尾随逗号)
--(…假设
@code
中永远不会有空条目)
--然后它将从这两个列表中读取派生的编号列表
--最后,它将在其
PartIndex

带铸造为
(
选择CAST(“”+REPLACE(@code,“,”)+“”)作为XML。查询(“/x[text()]”)作为CodeXml
,将(“”+替换(@value,“~”,“”)+”转换为XML)转换为ValueXml
)
,代码派生为
(
选择(ORDER BY(SELECT NULL))上方的行号()作为PartIndex
,x.value('text()[1]','nvarchar(max')作为代码部分
从铸造
交叉应用CodeXml.nodes('/x')A(x)
)
,值派生为
(
选择(ORDER BY(SELECT NULL))上方的行号()作为PartIndex
,x.value('text()[1]','nvarchar(max')作为ValuePart
从铸造
交叉应用ValueXml.nodes('/x')A(x)
)
选择cd.PartIndex
,代码部分
,ValuePart
从代码派生cd
内部联接值派生自cd上的vd。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
只需在其中添加一个简单的
即可将其减少到所需的值


免责声明:不保证使用
行编号和
顺序的编号(选择空)
将返回正确的序列,但为了更好地使用SQL Server 2016+。

这应该非常简单。如果性能很重要,我建议使用拆分字符串。下面是一个简单、高性能的解决方案:

DECLARE @searchFor INT = 10490;

SELECT code = s1.item, s2.item
FROM dbo.DelimitedSplit8K(@code,',')  s1
JOIN dbo.DelimitedSplit8K(@value,'~') s2 ON s2.ItemNumber = s1.ItemNumber-1
WHERE s1.Item = @searchFor;
结果:

code       item
---------- ------------
10490      Digital

好的,当我读到你们的数组时,10490是第5个。第1个是空的,第2个是10501等等。对不起,我在免责声明中提到第一个和最后一个逗号不应计入第1个数组。这是为哪个版本的SQL Server设计的?@Tony抱歉,错过了那个版本。SQL Server 2014这将起作用。Op只需为string_split.创建一个UDF,然后使用该指令2016年内置字符串分割的ead.OP提到,他不能使用函数或存储过程。抱歉..错过了这一点!注意:
string\u split()
不保证返回正确的顺序。如果您在v2016+中需要位置安全拆分方法,最好使用
OPENJSON
或@Pm Duda周围的各种函数之一……您的第二种方法奏效了。我只需要看看3个建议的工作版本中哪一个更有效,因为它需要经过大量的重新记录ds.谢谢!Hi Shungo,我不会说它的设计不好。它从来没有被设计成用SQL解析。它被设计成用C#解析,这很容易做到。这是一个审计表,你可能已经猜到了,通常这就是审计表的样子。尽管如此,你的解决方案很有效,我非常感谢你的帮助p!很抱歉没有给出完整的图片,但这需要在左连接的SELECT语句中完成。类似于:LEFT JOIN audit on audit.auditid=(我需要使用TOP 1和ORDER BY here查找特定记录)。我该怎么做呢?@Tony,把我的最后一个
SELECT
放在另一个
cte
中,并像使用任何其他表一样使用它……嗨@Shnugo,我不是一个很强的SQL开发人员,也从来没有使用过cte,所以所有这些对我来说都是新的。我尝试过,但没有尝试过
code       item
---------- ------------
10490      Digital