【问题标题】:Extracting data between two delimiters in SQL Server?在 SQL Server 中的两个分隔符之间提取数据?
【发布时间】:2018-08-06 22:30:14
【问题描述】:

我有一列包含aaa|bbb|ccc格式的数据,需要分别从数据中提取aaa、bbb和ccc。

我试过了

SELECT  
    SUBSTRING(Column1, 0, CHARINDEX('|', Column1)) AS [First],
    SUBSTRING(Column1, CHARINDEX('|', Column1)  + 1, LEN(Column1)) AS [Second]
FROM
    Table1

输出:

aaa [FIRST],bbb|ccc [Second] 

但我需要aaa [FIRST],bbb [Second],ccc [Third]

【问题讨论】:

  • 什么版本的 SQL Server?如果您使用的是 SQL Server 2016 或更高版本,则可以使用 STRING_SPLIT 函数。
  • @squillman 我正在使用 SQL Server 2014。
  • 您可以使用字符串拆分功能。这是Jeff Moden's。这是my modified version。

标签: sql sql-server substring


【解决方案1】:

如果你有一个格式完全相同的字符串(三次),由| 分隔,那么你可以PARSENAME() :

select col1, parsename(cols, 3) fisrt, parsename(cols, 2) second, parsename(cols, 1) third
from table1 t1 cross apply
     ( values (replace(col1, '|', '.')) 
     ) t2 (cols);

【讨论】:

    【解决方案2】:

    您可以尝试以下方式使用函数charindex、SUBSTRING 和REVERSE

     with t as (select 'aaa|bbb|ccc' as val)
    select t.*,
           LEFT(val, charindex('|', val) - 1),
       SUBSTRING(val, charindex('|', val)+1, len(val) - CHARINDEX('|', reverse(val)) - charindex('|', val)),
           REVERSE(LEFT(reverse(val), charindex('|', reverse(val)) - 1))
    from t;
    
    val             
    aaa|bbb|ccc     aaa     bbb     ccc
    

    【讨论】:

      【解决方案3】:

      您可以使用公用表表达式 (CTE) 拆分列中的值,因为拆分功能在您的 SQL Server 版本中不可用

      WITH CTE(userString,startIndex,EndIndex)
      AS
      (
          SELECT Column1,1,CHARINDEX('|',Column1)
          FROM Table1
      
          UNION ALL
      
          SELECT Column1, EndIndex+1,CHARINDEX('|',Column1,EndIndex+1)
          FROM CTE
          WHERE EndIndex !=0 
      )
      SELECT SUBSTRING(userString,
                      startIndex,
                      CASE WHEN EndIndex > 0 
                      THEN EndIndex - startIndex ELSE LEN(Column1) END) 
             as splitVALUES
      FROM CTE
      

      【讨论】:

        【解决方案4】:

        我一直这样做,它对我很有效:

        DECLARE @delimString VARCHAR(255) = 'aaa|bbb|ccc';
        
        DECLARE @xml XML = '<val>' + REPLACE( @delimString, '|', '</val><val>' ) + '</val>'
        
        SELECT 
            x.f.value( '.', 'VARCHAR(50)' ) AS val
        FROM @xml.nodes( '//val' ) x( f );
        

        返回

        +-----+
        | val |
        +-----+
        | aaa |
        | bbb |
        | ccc |
        +-----+
        

        如果您正在寻找列式返回,并且知道您将始终只有需要解析三个值,那么您也许可以像下面的示例一样摆脱困境。您可以在 SSMS 中运行它。

        DECLARE @table TABLE ( [value] VARCHAR(255) );
        INSERT INTO @table ( [value] ) VALUES 
        ( 'aaa|bbb|ccc' )
        , ( '0A-PRDS|JQLM-1|1967' )
        , ( 'J1658|G-1|2003' );
        
        SELECT
            [value]
            , SUBSTRING( [value], 0, CHARINDEX( '|', [value] ) ) AS Column1
            , SUBSTRING( 
                [value]
                , ( CHARINDEX( '|', [value]) + 1 )  -- starting position of column 2.
                , CHARINDEX( '|', [value],  ( CHARINDEX( '|', [value] ) + 1 ) ) - ( CHARINDEX( '|', [value]) + 1 ) -- length of column two is the number of characters between the two delimiters.
            ) AS Column2
            , SUBSTRING(
                [value]
                , CHARINDEX( '|', [value], ( CHARINDEX( '|', [value] ) + 1 ) ) + 1
                , LEN( [value] )
            ) AS Column3
        FROM @table;
        

        返回

        +---------------------+---------+---------+---------+
        |        value        | Column1 | Column2 | Column3 |
        +---------------------+---------+---------+---------+
        | aaa|bbb|ccc         | aaa     | bbb     | ccc     |
        | 0A-PRDS|JQLM-1|1967 | 0A-PRDS | JQLM-1  | 1967    |
        | J1658|G-1|2003      | J1658   | G-1     | 2003    |
        +---------------------+---------+---------+---------+
        

        【讨论】:

        • Column1 和 Column3 运行良好,但 Column2 未获得预期结果,例如“0A-PRDS|JQLM-1|1967 第一阶段请求”和“J1658|G-1|2003 第三阶段”等字符串请求'
        • 你是对的。我已经相应地更新了我的示例。在您的情况下,PARSENAME 似乎是获得所需内容的最简单的方法。
        猜你喜欢
        • 1970-01-01
        • 2019-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-10
        • 1970-01-01
        • 2010-11-15
        • 2012-11-27
        相关资源
        最近更新 更多