2010-11-16 7 views
1

Из таблицы ниже, как можно преобразовать столбец Values в несколько столбцов, заполненных отдельными значениями, которые в настоящее время разделены запятыми? До преобразования:T-SQL - преобразовать столбец с разделителями-запятыми в несколько столбцов

Name Values 
---- ------ 
John val,val2,val3 
Peter val5,val7,val9,val14 
Lesli val8,val34,val36,val65,val71,val 
Amy val3,val5,val99 

Результат преобразования должен выглядеть следующим образом:

Name Col1 Col2 Col3 Col4 Col5 Col6 
---- ---- ---- ---- ---- ---- ---- 
John val val2 val3 
Peter val5 val7 val9 val14 
Lesli val8 val34 val36 val65 val71 val 
Amy val3 val5 val99 
+0

Пожалуйста форматировать ваши таблицы немного, таким образом мы можем сделать больше смысла того, что вы просите. – Stu

+0

Просто загруженное изображение, так как не удалось форматировать таблицу. – user219628

+0

Спасибо за отзыв. – user219628

ответ

3

Во-первых, какой продукт базы данных и версии вы используете? Если вы используете SQL Server 2005 и более поздних версиях можно написать Разделить определяемую пользователем функцию следующим образом:

CREATE FUNCTION [dbo].[Split] 
( 
    @DelimitedList nvarchar(max) 
    , @Delimiter varchar(2) = ',' 
) 
RETURNS TABLE 
AS 
RETURN 
    (
    With CorrectedList As 
     (
     Select Case When Left(@DelimitedList, DataLength(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      + @DelimitedList 
      + Case When Right(@DelimitedList, DataLength(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      As List 
      , DataLength(@Delimiter) As DelimiterLen 
     ) 
     , Numbers As 
     (
     Select TOP (Coalesce(Len(@DelimitedList),1)) Row_Number() Over (Order By c1.object_id) As Value 
     From sys.objects As c1 
      Cross Join sys.columns As c2 
     ) 
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position 
     , Substring (
        CL.List 
        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen  
        , CharIndex(@Delimiter, CL.list, N.Value + 1)       
         - (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen) 
        ) As Value 
    From CorrectedList As CL 
     Cross Join Numbers As N 
    Where N.Value < Len(CL.List) 
     And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter 
    ) 

Вы можете отделить ценности в вы хотите использовать что-то похожее на:

Select Name, Values 
From Table1 As T1 
Where Exists (
       Select 1 
       From Table2 As T2 
        Cross Apply dbo.Split (T1.Values, ',') As T1Values 
        Cross Apply dbo.Split (T2.Values, ',') As T2Values 
       Where T2.Values.Value = T1Values.Value 
        And T1.Name = T2.Name 
       ) 
+0

спасибо, он тоже работал – user219628

3

Вот решение, которое использует рекурсивный cte для генерации «table of numbers» (любезно предоставлено Itzik Ben-Gan), которое равно useful для всех проблем, включая разбиение строк, и PIVOT. SQL Server 2005 и далее. Полная таблица создает, вставляет и выбирает скрипт.

CREATE TABLE dbo.Table1 
(
    Name  VARCHAR(30), 
    [Values] VARCHAR(128) 
) 
GO 

INSERT INTO dbo.Table1 VALUES ('John', 'val,val2,val3') 
INSERT INTO dbo.Table1 VALUES ('Peter', 'val5,val7,val9,val14') 
INSERT INTO dbo.Table1 VALUES ('Lesli', 'val8,val34,val36,val65,val71,val') 
INSERT INTO dbo.Table1 VALUES ('Amy', 'val3,val5,val99') 
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 Name, [1] AS Column1, [2] AS Column2, [3] AS Column3, [4] AS Column4, [5] AS Column5, [6] AS Column6, [7] AS Column7 
FROM 
(SELECT Name, 
     ROW_NUMBER() OVER (PARTITION BY Name ORDER BY nums.n) AS PositionInList, 
     LTRIM(RTRIM(SUBSTRING(valueTable.[Values], nums.n, charindex(N',', valueTable.[Values] + N',', nums.n) - nums.n))) AS [Value] 
FROM Numbers AS nums INNER JOIN dbo.Table1 AS valueTable ON nums.n <= CONVERT(int, LEN(valueTable.[Values])) AND SUBSTRING(N',' + valueTable.[Values], n, 1) = N',') AS SourceTable 
PIVOT 
(
MAX([VALUE]) FOR PositionInList IN ([1], [2], [3], [4], [5], [6], [7]) 
) AS Table2 
GO 

--DROP TABLE dbo.Table1 

, который преобразует этот вывод

Name Values 
John val,val2,val3 
Peter val5,val7,val9,val14 
Lesli val8,val34,val36,val65,val71,val 
Amy val3,val5,val99 

к

Name Column1 Column2 Column3 Column4 Column5 Column6 Column7 
Amy val3 val5 val99 NULL NULL NULL NULL 
John val  val2 val3 NULL NULL NULL NULL 
Lesli val8 val34 val36 val65 val71 val  NULL 
Peter val5 val7 val9 val14 NULL NULL NULL 
+0

Я должен добавить, что недостатком этого является то, что вы не можете динамически изменять размер столбцов в зависимости от максимального количества значений в разделителе с запятой строка. Для этого вам нужно будет рассмотреть динамический SQL и создать количество столбцов, чтобы оно соответствовало максимальному количеству значений в любой из строк с разделителями. –