Sql server 2005 使用tsql返回字符串中第n个元素的索引
如何在SQL Server中返回字符串中第n个元素的索引。例如,我有字符串:a、b、c、d、e 现在我想在第三次昏迷之前接收所有元素,所以a,b,c。为了做到这一点,我需要有第三昏迷指数。Charindex不适合这里,因为我无法传递coma的数量,我需要索引。是否有任何内置功能可以做到这一点 更新,@Andriy M 嘿,你指给我的链接也很有用。下面我对显示的sql进行了一些修改,以获得我想要的:Sql server 2005 使用tsql返回字符串中第n个元素的索引,sql-server-2005,tsql,Sql Server 2005,Tsql,如何在SQL Server中返回字符串中第n个元素的索引。例如,我有字符串:a、b、c、d、e 现在我想在第三次昏迷之前接收所有元素,所以a,b,c。为了做到这一点,我需要有第三昏迷指数。Charindex不适合这里,因为我无法传递coma的数量,我需要索引。是否有任何内置功能可以做到这一点 更新,@Andriy M 嘿,你指给我的链接也很有用。下面我对显示的sql进行了一些修改,以获得我想要的: CREATE FUNCTION [dbo].[nthindexsub](@String varch
CREATE FUNCTION [dbo].[nthindexsub](@String varchar(8000), @Delimiter char(1), @DelimitersCount int)
returns varchar(8000)
as
begin
declare @Substring varchar(8000)
declare @temptable TABLE (itemindex int identity(1,1), items varchar(8000))
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return @Substring
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
select @Substring = COALESCE(@Substring + ',', '') + items from @temptable where itemindex <= @DelimitersCount
return @Substring;
end
结果是:a、b、c可以在TSQL中执行,但是TSQL不擅长(或设计用于)字符串操作,因此如果您经常调用它,它可能会很慢
创建一个索引可能更好。我不确定您为什么只需要索引?为什么不将它们拆分成行呢?处理行更快更好。下面是一个简单的TSQL拆分示例:
DECLARE @List varchar(500)
,@SplitOn char(1)
SELECT @List='aaa,bb,c,dd,eeee'
,@SplitOn=','
;WITH NumbersCTE AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number+1
FROM NumbersCTE
WHERE Number<LEN(@List)
)
, AllSplit AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY number) AS RowNumber
,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS ListValue
) AS InnerQuery
INNER JOIN NumbersCTE n ON n.Number < LEN(InnerQuery.ListValue)
WHERE SUBSTRING(ListValue, number, 1) = @SplitOn
)
SELECT
ListValue
FROM AllSplit
WHERE RowNumber<=3
在SQLServer2005中有很多方法可以拆分字符串。本文介绍了几乎每种方法的优缺点:
您需要创建一个拆分函数。这就是拆分函数的使用方式:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
但是在SQLServer中有很多方法可以分割字符串(在前面的示例中,我使用了CTE),请参阅前面的链接,其中解释了每种方法的优缺点
要使Numbers表方法起作用,您需要执行此一次性表设置,它将创建一个包含1到10000行的表Numbers
:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
设置数字表后,创建此拆分函数:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
输出:
ListValue
-----------------------
1
2
3
4
5
6777
(6 row(s) affected)
csv
-------------------------------------------------- -----------
aaa,bb,c,dd,eeee 9
aaa,bb,c,dd 9
aaa,bb,c 9
csv ThirdComma
------------------- -----------
aaa,bb,c,dd,eeee 9
aaa,bb,c,dd 9
aaa,bb,c 9
aaa,bb 7
aaa 4
NULL NULL
您可以像这样使用CSV字符串,不需要临时表:
SELECT
y.*
FROM YourTable y
INNER JOIN dbo.FN_ListToTable(',',@MyList) x ON y.pk=x.ListValue
Where y.aaa='5'
如果只需要前三个元素,请尝试按如下方式嵌套CHARINDEX:
DECLARE @YourTable table (csv varchar(50))
INSERT @YourTable VALUES ('aaa,bb,c,dd,eeee')
INSERT @YourTable VALUES ('aaa,bb,c,dd')
INSERT @YourTable VALUES ('aaa,bb,c')
INSERT @YourTable VALUES ('aaa,bb')
INSERT @YourTable VALUES ('aaa')
INSERT @YourTable VALUES (null)
SELECT
csv
,CHARINDEX(',',csv+',',CHARINDEX(',',csv+',',CHARINDEX(',',csv+',',0)+1)+1) AS ThirdComma
FROM @YourTable
WHERE CHARINDEX(',',csv,0)>0
AND CHARINDEX(',',csv+',',CHARINDEX(',',csv+',',CHARINDEX(',',csv+',',0)+1)+1)>0
输出:
ListValue
-----------------------
1
2
3
4
5
6777
(6 row(s) affected)
csv
-------------------------------------------------- -----------
aaa,bb,c,dd,eeee 9
aaa,bb,c,dd 9
aaa,bb,c 9
csv ThirdComma
------------------- -----------
aaa,bb,c,dd,eeee 9
aaa,bb,c,dd 9
aaa,bb,c 9
aaa,bb 7
aaa 4
NULL NULL
这将只返回有三个元素的行。如果有一个、两个和/或三个时需要,请尝试以下方法:
DECLARE @YourTable table (csv varchar(50))
INSERT @YourTable VALUES ('aaa,bb,c,dd,eeee')
INSERT @YourTable VALUES ('aaa,bb,c,dd')
INSERT @YourTable VALUES ('aaa,bb,c')
INSERT @YourTable VALUES ('aaa,bb')
INSERT @YourTable VALUES ('aaa')
INSERT @YourTable VALUES (null)
;WITH FindThird AS
(
SELECT csv, CHARINDEX(',',csv+',',CHARINDEX(',',csv+',',CHARINDEX(',',csv+',',0)+1)+1) AS ThirdComma
FROM @YourTable
)
SELECT
csv
,CASE
WHEN ThirdComma IS NULL OR ThirdComma=0 THEN LEN(csv)+1
ELSE ThirdComma
END AS ThirdComma
FROM FindThird
输出:
ListValue
-----------------------
1
2
3
4
5
6777
(6 row(s) affected)
csv
-------------------------------------------------- -----------
aaa,bb,c,dd,eeee 9
aaa,bb,c,dd 9
aaa,bb,c 9
csv ThirdComma
------------------- -----------
aaa,bb,c,dd,eeee 9
aaa,bb,c,dd 9
aaa,bb,c 9
aaa,bb 7
aaa 4
NULL NULL
这里解决了一个类似的问题:对不起,一开始你的问题搞错了。本以为需要搜索第n项,但结果却是需要字符串的前n项。但是,我再次指出,我的问题是,尽管对不同的问题要求不同的解决方案,但它包含了一个脚本,我认为它正是您所需要的。