我需要一个子字符串来从字段中提取数据

时间:2019-05-06 16:36:48

标签: sql-server tsql split

我有一个字段,其中包含格式为1_US_01_103_157_G014的字符。在给定的示例中可以看到,该字段中的字符由_连在一起。

我想创建一个Tsql来将每个字符提取到其自己的列中,例如,假设Column 1 = 1_US_01_103_157_G014。派生的第2列=1。第3列= US,第4列= 01,第5列= 103,第6列= 157,第7列= G014。

3 个答案:

答案 0 :(得分:1)

您可以替换下划线_,然后将结果转换为xml,然后进行处理。像这样的东西。

declare @tbl table(col1 varchar(50))
insert @tbl(col1) values ('1_US_01_103_157_G014')

;with cte as(
    select col1, cast('<t><x>'+REPLACE(col1,'_','</x><x>')+'</x></t>' as xml) x
    from @tbl
)
select col1,
    t.v.value('x[1]', 'varchar(20)') col2,
    t.v.value('x[2]', 'varchar(20)') col3,
    t.v.value('x[3]', 'varchar(20)') col4,
    t.v.value('x[4]', 'varchar(20)') col5,
    t.v.value('x[5]', 'varchar(20)') col6,
    t.v.value('x[6]', 'varchar(20)') col7
from cte
cross apply x.nodes('t') t(v)

答案 1 :(得分:0)

这是我建议的一种方法:

首先,您需要一个split函数将字符串转换为表格

go
create function [dbo].[Split]
(
    @String nvarchar(4000),
    @Delimiter nchar(1)
)
returns table
as
return
(
    with Split(stpos, endpos)
    as(
        select 0 as stpos, charindex(@Delimiter,@String) AS endpos
        union all
        select endpos+1, charindex(@Delimiter,@String,endpos+1)
            from Split
            where endpos > 0
    )
    select 'Id' = row_number() over (order by (select 1)),
        'Data' = substring(@String,stpos,coalesce(nullif(endpos,0),len(@String)+1)-stpos)
    from Split
)

现在您可以执行以下操作:

go
declare @inputString nvarchar(128) set @inputString = '1_US_01_103_157_G014'
select * from dbo.Split(@inputString, '_')

产生一个表: enter image description here

第二件事...您可以使用pivot operator将行转换为列

go
declare @inputString nvarchar(128) set @inputString = '1_US_01_103_157_G014'

SELECT 'values', [1], [2], [3], [4], [5], [6]  
FROM  
(select Id, Data from dbo.Split(@inputString, '_')) AS SourceTable  
PIVOT  
(  
max(Data)  
FOR Id IN ([1], [2], [3], [4], [5], [6])  
) AS PivotTable;  

pivot将产生以下结果:

enter image description here

从您的问题中不清楚您到底想做什么,但这是一个很好的起点。

我希望对您有帮助

答案 2 :(得分:0)

使用CROSS APPLY很容易。请注意,下面的temp变量使您可以对此进行测试。在您的环境中,您将使用正在处理的任何表替换@tbl。

-- Your table (change the query to point to your real table)
DECLARE @tbl TABLE(col1 VARCHAR(50))
INSERT @tbl(col1) VALUES ('1_US_01_103_157_G014');

SELECT
  C1 = t.col1,
  C2 = SUBSTRING(t.col1,1,d1.D-1), 
  C3 = SUBSTRING(t.col1,d1.D+1,d2.D-d1.D-1),
  C4 = SUBSTRING(t.col1,d2.D+1,d3.D-d2.D-1),
  C5 = SUBSTRING(t.col1,d3.D+1,d4.D-d3.D-1),
  C6 = SUBSTRING(t.col1,d4.D+1,d5.D-d4.D-1),
  C7 = SUBSTRING(t.col1,d5.D+1,8000)
FROM @tbl AS t
CROSS APPLY (VALUES(CHARINDEX('_',t.col1)))        AS d1(D)
CROSS APPLY (VALUES(CHARINDEX('_',t.col1,d1.D+1))) AS d2(D)
CROSS APPLY (VALUES(CHARINDEX('_',t.col1,d2.D+1))) AS d3(D)
CROSS APPLY (VALUES(CHARINDEX('_',t.col1,d3.D+1))) AS d4(D)
CROSS APPLY (VALUES(CHARINDEX('_',t.col1,d4.D+1))) AS d5(D);

返回

C1                     C2  C3   C4   C5   C6    C7
---------------------- --- ---- ---- ---- ----- -------
1_US_01_103_157_G014   1   US   01   103  157   G014