복붙노트

[SQL] T-SQL은 구분에 따라 문자열을 분할

SQL

T-SQL은 구분에 따라 문자열을 분할

나는 또는 존재하지 않을 수도 있습니다 구분에 따라 분할하고 싶은 몇 가지 데이터를 가지고있다.

예 데이터 :

John/Smith
Jane/Doe
Steve
Bob/Johnson

나는 이름과 성으로이 데이터를 분할하려면 다음 코드를 사용하고 있습니다 :

SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
       SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM   MyTable

결과는 내가 좋아하는 것 :

FirstName---LastName
John--------Smith
Jane--------Doe
Steve-------NULL
Bob---------Johnson

이 코드는 한 모든 행이 예상되는 구분 기호를 가지고 잘 작동하지만 오류 행을하지 않을 때 아웃 :

"Invalid length parameter passed to the LEFT or SUBSTRING function."

어떻게 제대로 일이 다시는 쓰기 수 있습니까?

해결법

  1. ==============================

    1.이 도움이 될 수 있음.

    이 도움이 될 수 있음.

    SELECT SUBSTRING(myColumn, 1, CASE CHARINDEX('/', myColumn)
                WHEN 0
                    THEN LEN(myColumn)
                ELSE CHARINDEX('/', myColumn) - 1
                END) AS FirstName
        ,SUBSTRING(myColumn, CASE CHARINDEX('/', myColumn)
                WHEN 0
                    THEN LEN(myColumn) + 1
                ELSE CHARINDEX('/', myColumn) + 1
                END, 1000) AS LastName
    FROM MyTable
    
  2. ==============================

    2.SQL 서버 2016+에 대한 답을 찾고있는 겁니다. 사용 내장 STRING_SPLIT 기능

    SQL 서버 2016+에 대한 답을 찾고있는 겁니다. 사용 내장 STRING_SPLIT 기능

    예 :

    DECLARE @tags NVARCHAR(400) = 'clothing,road,,touring,bike'  
    
    SELECT value  
    FROM STRING_SPLIT(@tags, ',')  
    WHERE RTRIM(value) <> '';  
    

    참조 : https://msdn.microsoft.com/en-nz/library/mt684588.aspx

  3. ==============================

    3.

    SELECT CASE 
            WHEN CHARINDEX('/', myColumn, 0) = 0
                THEN myColumn
            ELSE LEFT(myColumn, CHARINDEX('/', myColumn, 0)-1)
            END AS FirstName
        ,CASE 
            WHEN CHARINDEX('/', myColumn, 0) = 0
                THEN ''
            ELSE RIGHT(myColumn, CHARINDEX('/', REVERSE(myColumn), 0)-1)
            END AS LastName
    FROM MyTable
    
  4. ==============================

    4.단지 같은 사람에 대한 구분 작업과 문자열을 포함하는 행 필터링보십시오 :

    단지 같은 사람에 대한 구분 작업과 문자열을 포함하는 행 필터링보십시오 :

    SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
           SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
    FROM   MyTable
    WHERE CHARINDEX('/', myColumn) > 0
    

    또는

    SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
           SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
    FROM   MyTable
    WHERE myColumn LIKE '%/%'
    
  5. ==============================

    5.당신이 2016 아래 SQL Server 버전을 사용하는 경우에는 그냥 여러 구분 기호 문자열을 분할하는 다른 방법을주고 싶어.

    당신이 2016 아래 SQL Server 버전을 사용하는 경우에는 그냥 여러 구분 기호 문자열을 분할하는 다른 방법을주고 싶어.

    일반적인 아이디어는 문자열 내의 모든 문자를 분할 구분 기호의 위치를 ​​결정, 다음 구분 기호를 기준으로 문자열을 얻는 것입니다. 다음은 샘플입니다 :

    -- Sample data
    DECLARE @testTable TABLE (
        TestString      VARCHAR(50)
    )
    INSERT INTO @testTable VALUES 
        ('Teststring,1,2,3')
        ,('Test')
    
    DECLARE @delimiter VARCHAR(1) = ','
    
    -- Generate numbers with which we can enumerate
    ;WITH Numbers AS (
        SELECT 1 AS N
    
        UNION ALL 
    
        SELECT N + 1
        FROM Numbers 
        WHERE N < 255
    ), 
    -- Enumerate letters in the string and select only the delimiters
    Letters AS (
        SELECT  n.N
                , SUBSTRING(t.TestString, n.N, 1) AS Letter
                , t.TestString 
                , ROW_NUMBER() OVER (   PARTITION BY t.TestString
                                        ORDER BY n.N
                                    ) AS Delimiter_Number 
        FROM Numbers n
            INNER JOIN @testTable t
                ON n <= LEN(t.TestString)
        WHERE SUBSTRING(t.TestString, n, 1) = @delimiter 
    
        UNION 
    
        -- Include 0th position to "delimit" the start of the string
        SELECT  0
                , NULL
                , t.TestString 
                , 0
        FROM @testTable t 
    )
    -- Obtain substrings based on delimiter positions
    SELECT  t.TestString 
            , ds.Delimiter_Number + 1 AS Position
            , SUBSTRING(t.TestString, ds.N + 1, ISNULL(de.N, LEN(t.TestString) + 1) - ds.N - 1) AS Delimited_Substring 
    FROM @testTable t
        LEFT JOIN Letters ds
            ON t.TestString = ds.TestString 
        LEFT JOIN Letters de
            ON t.TestString = de.TestString 
            AND ds.Delimiter_Number + 1 = de.Delimiter_Number  
    OPTION (MAXRECURSION 0)
    
  6. ==============================

    6.잘 작동 위의 예는 하나의 구분이있을 때,하지만 여러 구분 기호를 잘 확장되지 않습니다. 이것은 단지 SQL 서버 2016 이상 작동 않습니다.

    잘 작동 위의 예는 하나의 구분이있을 때,하지만 여러 구분 기호를 잘 확장되지 않습니다. 이것은 단지 SQL 서버 2016 이상 작동 않습니다.

    /*Some Sample Data*/
    DECLARE @mytable TABLE ([id] VARCHAR(10), [name] VARCHAR(1000));
    INSERT INTO @mytable
    VALUES ('1','John/Smith'),('2','Jane/Doe'), ('3','Steve'), ('4','Bob/Johnson')
    
    
    /*Split based on delimeter*/
    SELECT P.id, [1] 'FirstName', [2] 'LastName', [3] 'Col3', [4] 'Col4'
    FROM(
        SELECT A.id, X1.VALUE, ROW_NUMBER() OVER (PARTITION BY A.id ORDER BY A.id) RN
        FROM @mytable A
        CROSS APPLY STRING_SPLIT(A.name, '/') X1
        ) A
    PIVOT (MAX(A.[VALUE]) FOR A.RN IN ([1],[2],[3],[4],[5])) P
    
  7. ==============================

    7.

    ALTER FUNCTION [dbo].[split_string](
              @delimited NVARCHAR(MAX),
              @delimiter NVARCHAR(100)
            ) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
    AS
    BEGIN
      DECLARE @xml XML
      SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'
    
      INSERT INTO @t(val)
      SELECT  r.value('.','varchar(MAX)') as item
      FROM  @xml.nodes('/t') as records(r)
      RETURN
    END
    
  8. from https://stackoverflow.com/questions/21768321/t-sql-split-string-based-on-delimiter by cc-by-sa and MIT license