Разделить один столбец на несколько строк
Может ли кто-нибудь сказать мне, как это сделать? Столбец в моей таблице, в некоторых случаях, содержит значения, разделенные запятыми. Если это так, мне нужно создать новые строки для этих значений.
Кроме того, в качестве примера таблица содержит 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), и я тоже в процессе написания статьи.