Разделить один столбец на несколько строк - PullRequest
9 голосов
/ 23 ноября 2010

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

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

Ответы [ 4 ]

8 голосов
/ 23 ноября 2010

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

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)  = '') 

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

3 голосов
/ 23 ноября 2010

Еще одна из многих функций разделения строк.Это похоже на answer @Byron Whitlock, но вместо использования 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','
3 голосов
/ 23 ноября 2010

Вы можете написать табличную функцию и присоединить к ней свой столбец с помощью 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
0 голосов
/ 08 мая 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...