在sql中从字符串中分隔字符

时间:2018-01-08 20:45:50

标签: sql-server

我有一个看起来像这样的变量:

10000001 - ppppppp pppppp - ffffffff ffff - jjjj

我需要得到:

ffffffff ffff as 'column1'
jjjj  as 'column2'

第二和第三之后的字符长度' - '连字符可以有所不同。

我尝试了以下代码 - 它可以工作,但它似乎不是最有效的方式,因为我使用+18而且我担心字符长度可能会有所不同。

select case_id, 
LEFT(status_place,CHARINDEX('-',status_place)) numberID, 
SUBSTRING(status_place,CHARINDEX('-',status_place)+1,LEN(status_place)) todel,
SUBSTRING(status_place,CHARINDEX('-',status_place)+18,LEN(status_place)) Together
into #Prefinal
from [DD_PLACES]

select *,
LEFT(together,CHARINDEX('-',together)) Agency,
right(together, len(together) - charindex('-', together)) as 'Program'
into #final
from #Prefinal
select C_id, Agency, Program 
from #final
drop table #prefinal
drop table #final

2 个答案:

答案 0 :(得分:2)

ParseName非常适合

示例

Declare @YourTable table (ID int,status_place varchar(max))
Insert Into @YourTable values
(1,'10000001 - ppppppp pppppp - ffffffff ffff - jjjj')

Select ID
      ,column1 = PARSENAME(replace(status_place,' - ','.'),2)
      ,column2 = PARSENAME(replace(status_place,' - ','.'),1)
 From  @YourTable

<强>返回

ID  column1         column2
1   ffffffff ffff   jjjj
  

编辑 - 允许更多破折号

Declare @YourTable table (ID int,status_place varchar(max))
Insert Into @YourTable values
 (1,'10000001 - ppppppp pppppp - ffffffff ffff - jjjj')
,(2,'100000001 - Prrrrrrr Record - Viiiiiii Niiii Seeeeee Of Nnn Yyyy - Vvvvv - Mannnnnnn AAA')

Select ID
      ,column1 = convert(xml,'<x>'+replace(status_place,' - ','</x><x>')+'</x>').value('/x[3]','varchar(100)')
      ,column2 = convert(xml,'<x>'+replace(status_place,' - ','</x><x>')+'</x>').value('/x[4]','varchar(100)')
 From @YourTable

返回

ID  column1                             column2
1   ffffffff ffff                       jjjj
2   Viiiiiii Niiii Seeeeee Of Nnn Yyyy  Vvvvv

答案 1 :(得分:0)

对我来说,你的方法接近结果,因为CHARINDEX在SQL查询中很快。因此,我会保留您的初始方法,并专注于解决您的问题:您不想硬编码连字符的位置,因为它们不是固定的。

您可以使用CHARINDEX函数的第三个选项来执行此操作,该选项指示从哪个点开始搜索。既然你对文本字符串的右侧感兴趣,我建议使用REVERSE将结尾放在开头。然后再次REVERSE将结果按正确顺序排列。您可以复制下面的整个代码并在SQL Server中运行它。

DECLARE @table TABLE (status_place VARCHAR(255))
INSERT INTO @table (status_place) VALUES ('10000001 - ppppppp pppppp - ffffffff ffff - jjjj')
INSERT INTO @table (status_place) VALUES ('10000001 - ppppppp ppppp - ffffffff ff - jjjj')
INSERT INTO @table (status_place) VALUES ('10000001 - ppppppp pppp - ffffffff ffff - jjjj')
INSERT INTO @table (status_place) VALUES ('10000001 - ppppppp ppppppp - ffffffffff ffff - jjjj')
INSERT INTO @table (status_place) VALUES ('10000001 - ppppppp pppppppppp - fffffffffffff ffff - jjjj')
INSERT INTO @table (status_place) VALUES ('10000001 - ppppppp pppp - ffff ffff - jjjj')

UPDATE @table SET status_place = (LTRIM(RTRIM(status_place)))

SELECT 
    status_place,
    REVERSE (status_place) AS reverse_status_place, 
    LTRIM(RTRIM(
    REVERSE ( 
        SUBSTRING   (
            REVERSE(status_place),
            0,
            CHARINDEX('-',REVERSE(status_place),0)
                    ) 
            ) 
    )) AS column1,
    LTRIM(RTRIM(
    REVERSE (
        SUBSTRING   
        (
            REVERSE(status_place),
            CHARINDEX('-',REVERSE(status_place),0)+1,
            (   
                (   CHARINDEX   (
                        '-',
                        REVERSE(status_place),
                        CHARINDEX('-',REVERSE(status_place),0)+1
                                )
                )
                -
                (   CHARINDEX('-',REVERSE(status_place),0)+1    )
            )
        ) 
    )
    )) AS column2
FROM @table

我的代码的快速解释:首先我创建一个内存表,并为连字符加载不同位置的几种可能性。然后,我使用LTRIM和RTRIM删除前导和训练空间。这是一个标准的良好实践(除非你想保留这些空格),因为我们将计算字符和空格可能会产生噪音,因为一些SQL内置函数会计算它们,其他则不会。所以摆脱不必要的空间。

然后我选择了status_place和它的REVERSE,只是为了帮助调试。 下一部分看起来很复杂但不是:

首先是column1:它是REVERSE(status_place)的SUBSTRING,然后再次REVERSED。该子字符串有3个参数:列名,起始点和长度。起点是0,长度是第一个连字符的CHARINDEX(首先是因为我们已经颠倒了文本)。

然后是第二列,有点棘手:它是列的REVERSE的另一个子串,但它从第一个连字符+1的位置开始,并且如果第一个和第二个连字符之间的距离有长度。

第一个连字符和第二个连字符之间的距离是第二个连字符的位置减去第一个连字符的位置。我们已经有了第一个连字符的位置,所以我们需要获得第二个连字符的位置。

通过使用CHARINDEX函数的第三个参数获得位置第二个连字符:起始点。作为起点,我们使用第一个超级+1的位置,然后CHARINDEX开始在第一个连字符之后搜索下一个连字符,即第二个连字符。 我们有SUBSTRING的长度。

然后再次翻转每个,我使用LTRIM和RTRIM来清理前导和尾随空格。