如何通过字符串中的定界符交换字符?

时间:2018-06-28 14:52:25

标签: sql sql-server

假设我有一列Address

Address
NYC, NY State, USA
London, xxx, England

我想在第一个定界符','之前和之后交换字符。

所需的输出是

Address
NY State, NYC, USA
xxx, London, England

我认为substringcharindex可能会有所帮助,但我不确定如何解决。

3 个答案:

答案 0 :(得分:2)

使用PARSENAME

declare @table table (addy varchar(64))
    insert into @table
    values
    ('NYC, NY State, USA'),
    ('London, xxx, England'),
    ('Missouri, St. Louis, USA')

select
    replace(
    parsename(replace(replace(addy,'.','^'),',','.'),2) 
    + ', ' 
    + parsename(replace(replace(addy,'.','^'),',','.'),3) 
    + ', ' 
    + parsename(replace(replace(addy,'.','^'),',','.'),1)
    ,'^','.') 
from @table

这是一个常见的函数,当有4个或更少的部分时,用分隔符将字符串分开。对于您的情况,3.我们只需要用逗号替换逗号即可。 (并在需要时使用连字符或其他东西)

STUFFRIGHTLEN,还有其他一些字符串操作。

select
    stuff(right(addy,len(addy) - charindex(',',addy)),charindex(',',right(addy,len(addy) - charindex(',',addy))),0, ', ' + substring(addy,0,CHARINDEX(',',addy)) )
from @table

首先,我们将所有内容都放在第一个逗号之间

substring(addy,0,CHARINDEX(',',addy))

然后,我们在第一个逗号之后找到所有内容:

right(addy,len(addy) - charindex(',',addy))

最后,我们将它们与STUFF的字符串子集组合在一起,以从逗号开始将第一部分插入第二部分。

stuff(right(addy,len(addy) - charindex(',',addy)),charindex(',',right(addy,len(addy) - charindex(',',addy))),0, ', ' + substring(addy,0,CHARINDEX(',',addy)) )

答案 1 :(得分:2)

也许是另一个选择

示例

Declare @YourTable table (ID int,[Address] varchar(150))
Insert Into @YourTable values 
 (1,'NYC, NY State, USA')
,(2,'London, xxx, England')

Select A.ID
      ,NewString = concat(Pos2,', '+Pos1,', '+Pos3)
 From  @YourTable A
 Cross Apply (
                 Select Pos1 = n.value('/x[1]','varchar(max)')
                       ,Pos2 = n.value('/x[2]','varchar(max)')
                       ,Pos3 = n.value('/x[3]','varchar(max)')
                  From  (Select cast('<x>' + replace([Address],',','</x><x>')+'</x>' as xml) as n) X
             ) B

返回

ID   NewString
1    NY State, NYC,  USA
2    xxx, London,  England

答案 2 :(得分:0)

如果您要在不使用字符串拆分器的情况下执行此操作,则可以使用以下方法(只要地址分为三部分):

WITH VTE AS(
    SELECT *
    FROM (VALUES('NYC, NY State, USA'),
                ('London, xxx, England')) V([Address]))
SELECT V.[Address],
       SUBSTRING([Address], CI1.CI +1, CI2.CI-CI1.CI) + LEFT(V.[Address], CI1.CI) + RIGHT(V.[Address], LEN(V.[Address]) - CI2.CI)
FROM VTE V
     CROSS APPLY(VALUES(CHARINDEX(',',V.[Address]))) CI1(CI)
     CROSS APPLY(VALUES(CHARINDEX(',',V.[Address], CI1.CI + 1))) CI2(CI);

但是,如果可以使用提供顺序位置的分隔器(例如delimitedsplit8k),则可以执行以下操作:

USE Sandbox;
Go

WITH VTE AS(
    SELECT *
    FROM (VALUES('NYC, NY State, USA'),
                ('London, xxx, England')) V([Address]))
SELECT V.[Address],
       STUFF((SELECT ',' + item
              FROM dbo.DelimitedSplit8K(V.[Address],',') DS
              ORDER BY CASE DS.ItemNumber WHEN 1 THEN 2
                                          WHEN 2 THEN 1
                                          ELSE DS.ItemNumber END
              FOR XML PATH('')),1,1,'')
FROM VTE V;