Разделить один столбец на несколько строк

Может ли кто-нибудь сказать мне, как это сделать? Столбец в моей таблице, в некоторых случаях, содержит значения, разделенные запятыми. Если это так, мне нужно создать новые строки для этих значений.

Кроме того, в качестве примера таблица содержит 1 строку и 4 столбца Col1 | Col2 | Col3 | Col4 со следующими значениями A | B | C | 1,2,3 соответственно. Итак, Col4 содержит строку "1,2,3", и мне нужно разбить значения, разделенные запятыми, и поместить их на собственные строки, чтобы таблица содержала 1 строку, где 1 2 и 3 были на собственных линиях в Col4.

Ответ 1

Я думаю, вы можете это сделать:

SELECT
    T.id, RIGHT(LEFT(T.csv,Number-1),
    CHARINDEX(',',REVERSE(LEFT(','+T.csv,Number-1))))
FROM
    master..spt_values,
    your_table T
WHERE
    Type = 'P' AND Number BETWEEN 1 AND LEN(T.csv)+1
    AND
    (SUBSTRING(T.csv,Number,1) = ',' OR SUBSTRING(T.csv,Number,1)  = '') 

Код был бесстыдно украден из этого сайта.

Ответ 2

Вы можете написать функцию таблицы и присоединиться к ней с помощью CROSS APPLY. Вот моя версия.

CREATE FUNCTION dbo.Splitter(@text nvarchar(max), @separator nvarchar(100))
RETURNS @result TABLE (i int, value nvarchar(max))
AS
BEGIN
    DECLARE @i int
    DECLARE @offset int
    SET @i = 0

    WHILE @text IS NOT NULL
    BEGIN
        SET @i = @i + 1
        SET @offset = charindex(@separator, @text)
        INSERT @result SELECT @i, CASE WHEN @offset > 0 THEN LEFT(@text, @offset - 1) ELSE @text END
        SET @text = CASE WHEN @offset > 0 THEN SUBSTRING(@text, @offset + LEN(@separator), LEN(@text)) END
    END
    RETURN
END

Ответ 3

Еще одна из многих функций разделения строк. Это похоже на @Byron Whitlock answer, но вместо использования master..spt_values ​​использует cte для создания таблицы чисел. SQL Server 2005 и далее.

CREATE TABLE dbo.Table1 
(
    Col1        CHAR(1),
    Col2        CHAR(1),
    Col3        CHAR(1),
    Col4        VARCHAR(50)
)
GO

INSERT INTO dbo.Table1 VALUES ('A','B','C','1,2,3')
GO

SELECT * FROM dbo.Table1;
GO

WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
Numbers AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L3)
SELECT  Col1, Col2, Col3,        
        LTRIM(RTRIM(SUBSTRING(valueTable.Col4, nums.n, charindex(N',', valueTable.Col4 + N',', nums.n) - nums.n))) AS [Value]
FROM   Numbers AS nums INNER JOIN dbo.Table1 AS valueTable ON nums.n <= CONVERT(int, LEN(valueTable.Col4)) AND SUBSTRING(N',' + valueTable.Col4, n, 1) = N','

Ответ 4

Я знаю, что это более старое сообщение, но я подумал, что добавлю обновление. Таблица Tally Table и cteTally, основанная на таблице, имеют серьезную проблему. Они используют конкатенированные разделители и убивают их скорость, когда элементы становятся шире, а строки становятся длиннее.

Я исправил эту проблему и написал статью об этом, которая может быть найдена по следующему URL. http://www.sqlservercentral.com/articles/Tally+Table/72993/

Я также скажу вам, что парень по имени "Питер" сделал улучшение даже в этом коде (в обсуждении статьи). Статья по-прежнему интересна, и я буду обновлять вложения с улучшениями Peter на следующий день или два. Между моим главным улучшением и tweek, сделанным Peter, я не верю, что вы найдете более быстрое решение T-SQL для разделения VARCHAR (8000). Я также решил проблему для этой породы разветкителей для VARCHAR (MAX), и я тоже в процессе написания статьи.