SQL查询子字符串查询

时间:2011-03-18 23:13:42

标签: sql sql-server tsql

我在SQL Server 2008数据库中有一个数据库列,其中包含由四个元素组成的VARCHAR数据,这些元素由下划线分隔;例如:

  

01_1234_ABC_TESTFOO
  02_2234_YES_FOO
  03_77653234_NO_BAR
  04_10922234_BLUE_TESTBAR
  05_8372_SKY_FOOBAR

我需要一个查询来将每行的前三个元素作为单独的列返回。我已设法使用以下代码分离前两个元素:

SELECT DISTINCT SUBSTRING(BarType, 1, CHARINDEX('_', BarType) - 1) as element1,
            SUBSTRING(BarType,CHARINDEX('_',BarType)+1, 
                CHARINDEX('_', SUBSTRING(BarType,CHARINDEX('_',BarType)+1,LEN(BarType)))-1) as element2
FROM dbo.TestDataFoo 

返回:

    element1   element2 
    01         1234     
    02         2234  
    03         77653234  
    04         10922234  
    05         8372

有人可以帮助我获取数据的第三个元素吗?我也有兴趣了解处理此问题的任何其他方法。

请参阅下文,了解生成测试数据的代码。

CREATE TABLE TestDataFoo (
id int PRIMARY KEY IDENTITY,
DateFoo datetime NOT NULL,
BarType varchar(50) NOT NULL)

INSERT INTO TestDataFoo (DateFoo, BarType)
VALUES(GetDate(), '01_1234_ABC_TESTFOO')
INSERT INTO TestDataFoo (DateFoo, BarType)
VALUES(GetDate(), '02_2234_YES_FOO')
INSERT INTO TestDataFoo (DateFoo, BarType)
VALUES(GetDate(), '03_77653234_NO_BAR')
INSERT INTO TestDataFoo (DateFoo, BarType)
VALUES(GetDate(), '04_10922234_BLUE_TESTBAR')
INSERT INTO TestDataFoo (DateFoo, BarType)
VALUES(GetDate(), '05_8372_SKY_FOOBAR')

由于

Nimi敬上

编辑:理想情况下,我想在不使用功能的情况下实现这一目标,但欢迎任何解决方案!

3 个答案:

答案 0 :(得分:1)

这是一个方便的功能,我认为可以解决这个问题。

create function [dbo].[fn_split]
    (
    @String nvarchar (4000)
    ,@Delimiter nvarchar (10)= ','
    )
returns @ValueTable table ([Value] nvarchar(4000))
as

/******************************************************************************
**      name: fn_split
**      desc: splits a delimited list into a table
**              select * from dbo.fn_split('01_1234_ABC_TESTFOO', '_')
*******************************************************************************/
begin

    declare @NextString nvarchar(4000)
    declare @Pos int
    declare @NextPos int
    declare @CommaCheck nvarchar(1)

    --Initialize
    set @NextString = ''
    set @CommaCheck = right(@String,1) 

    --Check for trailing Comma, if not exists, INSERT
    --if (@CommaCheck <> @Delimiter )
    set @String = @String + @Delimiter

    --Get position of first Comma
    set @Pos = charindex(@Delimiter,@String)
    set @NextPos = 1

    --Loop while there is still a comma in the String of levels
    while (@pos <>  0)  
    begin
        set @NextString = substring(@String,1,@Pos - 1)

        insert into @ValueTable ( [Value]) Values (@NextString)

        set @String = substring(@String,@pos +1,len(@String))

        set @NextPos = @Pos
        set @pos  = charindex(@Delimiter,@String)
    end

    return


end

GO

答案 1 :(得分:1)

;with cte as
(
  select cast('<r><i>'+replace(BarType,'_','</i><i>')+'</i></r>' as xml) as xmlcol
  from TestDataFoo
)
select 
  r.value('i[1]', 'varchar(50)') as element1,
  r.value('i[2]', 'varchar(50)') as element2,
  r.value('i[3]', 'varchar(50)') as element3
from cte
  cross apply xmlcol.nodes('r') r(r)  

答案 2 :(得分:1)

只需使用旧的 PARSENAME 技巧:

<强> SQL

SELECT 
    PARSENAME(REPLACE(MEGASTRING,'_','.'),4) AS COL1,
    PARSENAME(REPLACE(MEGASTRING,'_','.'),3) AS COL2,
    PARSENAME(REPLACE(MEGASTRING,'_','.'),2) AS COL3,
    PARSENAME(REPLACE(MEGASTRING,'_','.'),1) AS COL4
FROM (
    SELECT '01_1234_ABC_TESTFOO' AS MEGASTRING
    UNION ALL SELECT '02_2234_YES_FOO' AS MEGASTRING
    UNION ALL SELECT '03_77653234_NO_BAR' AS MEGASTRING
    UNION ALL SELECT '04_10922234_BLUE_TESTBAR' AS MEGASTRING
    UNION ALL SELECT '05_8372_SKY_FOOBAR' AS MEGASTRING
) data

<强>结果

COL1 COL2     COL3  COL4
01   1234     ABC   TESTFOO
02   2234     YES   FOO
03   77653234 NO    BAR
04   10922234 BLUE  TESTBAR
05   8372     SKY   FOOBAR