我在表格中有一个varchar
列。在本专栏中,结构是一致的,但长度可能略有不同。
以下是我可以处理的一些例子。请注意值如何符合相同的模式,但(策略编号和两个帐号)中包含的数值的长度可能略有不同。
DECLARE @historyDescription1 VARCHAR(50)
DECLARE @historyDescription2 VARCHAR(50)
DECLARE @historyDescription3 VARCHAR(50)
SET @historyDescription1 = 'Policy ZZ 998560-17 transferred from Account 0028397267 to Account 192135980'
SET @historyDescription2 = 'Policy ZZ 9985601-17-00 transferred from Account 128397267 to Account 792135980'
SET @historyDescription3 = 'Policy ZZ 998560789-17-00 transferred from Account 228397267 to Account 0192135980'
对于每条记录,我需要选择第一个帐号和第二个帐号。总会有两个在场。
像...一样的东西。
SELECT [first parsed value]+','+[second parsed value]
FROM myTable
WHERE [...]
这样我得到的结果就像......
0028397267,192135980
128397267,792135980
228397267,0192135980
我一直在玩SUBSTRING
,CHARINDEX
,LEFT
和RIGHT
无济于事。任何帮助表示赞赏。
答案 0 :(得分:2)
我试过这个,它似乎适用于你的样本值:
select substring(hist, pos1 + len1, pos2 - pos1 - len1 -1), substring(hist, pos2 + len2, lenhist - pos2 - len2 +1)
from (
select
pos1 = charindex('from Account', hist)
, pos2 = charindex('to Account', hist)
, len1 = len('from Account')
, len2 = len('to Account')
, lenhist = len(hist)
, *
from t
) x
我使用派生表来保持表达式的简单。
答案 1 :(得分:1)
你在这里发生了一些事情,这使得它看起来比它看起来更具挑战性。首先,您需要拆分输入字符串以分隔值。然后你需要再次将它们重新组合在一起。我在sql server central.com上使用Jeff Moden的字符串拆分器。你可以在这里找到他的文章,代码和关于这个主题的讨论。 http://www.sqlservercentral.com/articles/Tally+Table/72993/
既然我们可以有效地分割字符串,我们只需要将它重新组合在一起。我们可以使用STUFF和FOR XML技巧来做到这一点。
这适用于您发布的示例数据。如果值并非始终位于字符串中的位置,则面临挑战。
create table #Something (HistoryDescription varchar(200))
insert #Something
select 'Policy ZZ 998560-17 transferred from Account 0028397267 to Account 192135980' union all
select 'Policy ZZ 9985601-17-00 transferred from Account 128397267 to Account 792135980' union all
select 'Policy ZZ 998560789-17-00 transferred from Account 228397267 to Account 0192135980'
with parsedValues as
(
select *
from #Something s
cross apply dbo.DelimitedSplit8K(s.HistoryDescription, ' ')
where ItemNumber in (7, 10)
)
select HistoryDescription,
STUFF((select ',' + Item
from parsedValues pv2
where pv2.HistoryDescription = pv.HistoryDescription
order by pv2.ItemNumber
for xml path('')), 1, 1, '')
from parsedValues pv
group by pv.HistoryDescription
答案 2 :(得分:1)
charindex用于了解“帐户”一词的起始位置。 对于第二个“帐户”字样,您需要一个大于第一个的起始索引。
create table #test(
valor varchar(max)
)
insert into #test values('Policy ZZ 998560-17 transferred from Account 0028397267 to Account 192135980')
insert into #test values('Policy ZZ 9985601-17-00 transferred from Account 128397267 to Account 792135980')
insert into #test values('Policy ZZ 998560789-17-00 transferred from Account 228397267 to Account 0192135980')
select REPLACE(substring(
valor,
CHARINDEX('Account',valor)+8,
CHARINDEX('Account', valor,charindex('Account',valor))
)
,' to Account ',
',') as Accounts from #test
答案 3 :(得分:0)
DECLARE @tbl TABLE(historyDescription VARCHAR(500));
INSERT INTO @tbl VALUES
('Policy ZZ 998560-17 transferred from Account 0028397267 to Account 192135980')
,('Policy ZZ 9985601-17-00 transferred from Account 128397267 to Account 792135980')
,('Policy ZZ 998560789-17-00 transferred from Account 228397267 to Account 0192135980');
WITH SplitAtAccount AS
(
SELECT historyDescription
,CAST('<x>' + REPLACE(
REPLACE(
REPLACE(historyDescription,' transferred from Account ','SplitThisHere'
),' to Account ','SplitThisHere'
),'SplitThisHere','</x><x>') + '</x>' AS XML) Casted
FROM @tbl
)
SELECT Casted.value('(x/text())[1]','nvarchar(max)') AS Part1
,Casted.value('(x/text())[2]','nvarchar(max)') AS Part2
,Casted.value('(x/text())[3]','nvarchar(max)') AS Part3
FROM SplitAtAccount
结果
Part1 Part2 Part3
Policy ZZ 998560-17 0028397267 192135980
Policy ZZ 9985601-17-00 128397267 792135980
Policy ZZ 998560789-17-00 228397267 0192135980
答案 4 :(得分:0)
这不是一个比其他方法更好的方法,但它只是一个解析字符串的教育练习,使用CTE简化一些字符串表达式,并得出你想要的一般结果。这是一个更简单的,如果是“强力”方法,不依赖于STUFF / FOR XML技巧。它会进一步解析各个部分,包括政策编号,以防您出于其他目的而需要。
CREATE TABLE #Something (HistoryDescription varchar(200))
INSERT #Something
SELECT 'Policy ZZ 998560-17 transferred from Account 0028397267 to Account 192135980' union all
SELECT 'Policy ZZ 9985601-17-00 transferred from Account 128397267 to Account 792135980' union all
SELECT 'Policy ZZ 998560789-17-00 transferred from Account 228397267 to Account 0192135980'
WITH HistoryDescriptionFragments AS (
SELECT REVERSE(SUBSTRING(HistoryDescription, 1, CHARINDEX(' transferred', HistoryDescription) - 1)) AS ReversedPolicyFragment,
SUBSTRING(HistoryDescription, CHARINDEX('from Account ', HistoryDescription) + LEN('from Account ') + 1, LEN(HistoryDescription)) AS FromAccountFragment,
SUBSTRING(HistoryDescription, CHARINDEX('to Account ', HistoryDescription) + LEN('to Account ') + 1, LEN(HistoryDescription)) AS ToAccountFragment,
*
FROM #Something
), HistoryDescriptionParts AS (
SELECT REVERSE(SUBSTRING(ReversedPolicyFragment, 1, CHARINDEX(' ', ReversedPolicyFragment) - 1)) AS Policy,
SUBSTRING(FromAccountFragment, 1, CHARINDEX(' ', FromAccountFragment) - 1) AS FromAccount,
ToAccountFragment AS ToAccount,
HistoryDescription AS OriginalText
FROM HistoryDescriptionFragments
)
SELECT Policy, FromAccount, ToAccount, FromAccount + ',' + ToAccount AS DesiredOutput
FROM HistoryDescriptionParts
这给出了结果:
Policy FromAccount ToAccount DesiredOutput
--------------- ----------- ---------- --------------------
998560-17 0028397267 192135980 0028397267,192135980
9985601-17-00 128397267 792135980 128397267,792135980
998560789-17-00 228397267 0192135980 228397267,0192135980
作为解释......第一个CTE只是简化解析策略号所必需的。它将字符串拆分为包含您感兴趣的每个部分的片段,反转策略片段,以便通过仅搜索第一个空格更容易选择数字。第二个CTE优化了解析以获得所需的数据。最终的SELECT只是从CTE中选择,然后将你感兴趣的两件作品加入到最终的“Desired Output”中。