skip to Main Content

Table:

id | name    
1  | a,b,c    
2  | b

Output

id | name    
1  | a    
1  | b    
1  | c    
2  | b

I found this query online and it works fine in mySql Phpmyadmin query editor.

SELECT
  tablename.id, SUBSTRING_INDEX(SUBSTRING_INDEX (tablename.name, ',', numbers.n), ',', - 1) NAME
FROM  (SELECT 1 n UNION ALL
  SELECT 2 UNION ALL
  SELECT 3 UNION ALL
  SELECT 4) numbers
INNER JOIN tablename
    ON CHAR_LENGTH (tablename.name) - CHAR_LENGTH (REPLACE (tablename.name, ',', '')) >= numbers.n - 1
ORDER BY id, n

But in SQL Server, it throws

[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]'SUBSTRING_INDEX' is not a recognized built-in function name.
[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Incorrect syntax near 'numbers'.

Edit: This query uses in tableau development, Where TSQL is not working as expecting

enter image description here

3

Answers


  1. On SQL Server 2016 and later, we can use STRING_SPLIT here:

    SELECT id, value AS name  
    FROM yourTable
    CROSS APPLY STRING_SPLIT(name, ',')
    ORDER BY id, value;
    
    Login or Signup to reply.
  2. Try this:

    DECLARE @DataSource TABLE
    (
        [ID] INT
       ,[name] VARCHAR(24)
    );
    
    INSERT INTO @DataSource ([ID], [Name])
    VALUES (1, 'a,b,c')
          ,(2, 'b');
    
    WITH DataSource ([ID], [nameXML]) AS
    (
        SELECT [ID]
              ,CAST('<a>' + REPLACE([name], ',', '</a><a>')+ '</a>' AS XML)
        FROM @DataSource
    )
    
    SELECT [ID]
          ,T.c.value('.', 'VARCHAR(100)')
    FROM DataSource DS
    CROSS APPLY [nameXML].nodes('./a') T(c);
    
    Login or Signup to reply.
  3. You could use a recursive CTE as the following

    CREATE TABLE TBL(
      Id INT,
      String VARCHAR(45)
    );
    
    INSERT TBL VALUES
    (1, 'a,b,c'),
    (2, 'b');
    
    WITH CTE(Id, Chr, String) AS
    (
      SELECT Id,
             CAST(LEFT(String, CHARINDEX(',', String + ',') - 1) AS VARCHAR(20)),
             STUFF(String, 1, CHARINDEX(',', String + ','), '')
      FROM TBL
      UNION ALL
      SELECT Id,
             CAST(LEFT(String, CHARINDEX(',', String + ',') - 1) AS VARCHAR(20)),
             STUFF(String, 1, CHARINDEX(',', String + ','), '')
      FROM CTE
      WHERE String > ''
    )
    SELECT Id,
           Chr
    FROM CTE
    ORDER BY Id;
    

    Online demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search