提取每组两个不同字符串之间的每个字符串
Posted
技术标签:
【中文标题】提取每组两个不同字符串之间的每个字符串【英文标题】:Extract each string between each set of two different strings 【发布时间】:2019-01-10 17:17:06 【问题描述】:如果我有例如字符串:
'x(abc),y(def),z(ghi)'
如何提取逗号分隔的字符串:
'abc,def,ghi'
或字符串表:
'abc'
'def'
'ghi'
存在于'('
和')'
两个字符串之间?
它们是用逗号分隔的,但每个“元素”可以是可变长度的。
【问题讨论】:
您是否在一个单元格中存储多个值? 【参考方案1】:如果对 TVF 开放。作为 TVF,如果您的数据在表格中,则很容易在 CROSS APPLY
中使用。
示例
Declare @S varchar(max) = 'x(abc),y(def),z(ghi)'
Select * from [dbo].[tvf-Str-Extract](@S,'(',')')
退货
RetSeq RetPos RetVal
1 3 abc
2 10 def
3 17 ghi
感兴趣的功能
CREATE FUNCTION [dbo].[tvf-Str-Extract] (@String varchar(max),@Delimiter1 varchar(100),@Delimiter2 varchar(100))
Returns Table
As
Return (
with cte1(N) as (Select 1 From (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) as (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A ),
cte3(N) as (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1),
cte4(N,L) as (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-S.N,8000) From cte3 S)
Select RetSeq = Row_Number() over (Order By N)
,RetPos = N
,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1)
From ( Select *,RetVal = Substring(@String, N, L) From cte4 ) A
Where charindex(@Delimiter2,RetVal)>1
)
/*
Max Length of String 1MM characters
Declare @String varchar(max) = 'Dear [[FirstName]] [[LastName]], ...'
Select * From [dbo].[tvf-Str-Extract] (@String,'[[',']]')
*/
【讨论】:
你需要把它放在 Git 上,用一个很好的自述文件解释它,哈哈 @scsimon 谢谢你的笑容:) 好吧,我不明白,但它就像一个黑匣子!最大长度是多少? 1MM 个字符? @TDP 只是给我自己的评论/注释。我们创建了一个最多 1MM 行的临时计数表。【参考方案2】:您可以使用charindex
,如下所示:
declare @temp table
(val nvarchar(50))
insert into @temp values ('x(abc)')
insert into @temp values ('y(def)')
insert into @temp values ('z(ghi)')
SELECT
SUBSTRING(val,CHARINDEX('(', val) + 1,CHARINDEX(')', val) - CHARINDEX('(', val) - 1) as Val
from @temp
参考:SQL Select values inside parenthesis
编辑:如果它是一行,包括括号内的许多值,则需要先根据逗号对其进行拆分。对于 SQL 2008,我多年来一直使用此链接中指定的拆分函数,感谢 Andy:T-SQL split string
创建下面的函数:
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX(',', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
END
INSERT INTO @returnList
SELECT @stringToSplit
RETURN
END
看到这个:SELECT * FROM dbo.splitstring('x(abc),y(def),z(ghi)')
这样,您可以根据逗号拆分数据并使用我提到的第一个 charindex 策略。
【讨论】:
我认为他们只有 1 行数据而不是 3 我过去使用过类似的解析/拆分功能。我对使用 tally 或 xml 方法的性能提升感到震惊。 我会升级到非循环方法,但这个答案并不正确:)。 sqlservercentral.com/articles/Tally+Table/72993 感谢您的回答。我选择了另一个,因为它实际上不是充当分隔符的 '(' 和 ')',而且我不想使用循环,因为实际的字符串可能很长。以上是关于提取每组两个不同字符串之间的每个字符串的主要内容,如果未能解决你的问题,请参考以下文章