web-dev-qa-db-ja.com

複数の行に値を分割する

重複の可能性:
カンマ区切りの文字列を個々の行に変換する

ストアドプロシージャから次の出力があり、値を複数の行に分割する最良の方法を考えていました。

reference   name                            subjects       subjectstitle
LL9X81MT    Making and Decorating Pottery   F06,F27,F38       NULL

サブジェクトフィールドをカンマでトリミングし、情報を3行に複製して、データが次のようになるようにする必要があります。

reference   name                            subjects       subjectstitle
LL9X81MT    Making and Decorating Pottery   F06       NULL
LL9X81MT    Making and Decorating Pottery   F27       NULL
LL9X81MT    Making and Decorating Pottery   F38       NULL

私はMSSQL Server 2008を使用してこれらのSPをセットアップしていますが、サブジェクトフィールドを分割する方法についてのヘルプが必要です。

ありがとう、

6
PipBoy

次のようなテーブル値分割関数を使用することをお勧めします。

create FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
returns @temptable TABLE (items varchar(MAX))       
as       
begin      
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return 
end;

次に、outer applyを使用してテーブルに参加できます。

select t1.reference,
  t1.name,
  t1.subjectstitle,
  i.items subjects
from yourtable t1
outer apply dbo.split(t1.subjects, ',') i

このような結果を与える:

| REFERENCE |                          NAME | SUBJECTSTITLE | SUBJECTS |
------------------------------------------------------------------------
|  LL9X81MT | Making and Decorating Pottery |        (null) |      F06 |
|  LL9X81MT | Making and Decorating Pottery |        (null) |      F27 |
|  LL9X81MT | Making and Decorating Pottery |        (null) |      F38 |

デモを使用したSQLフィドル を参照してください

分割関数なしでこれを実行したい場合は、CTEを使用できます。

;with cte (reference, name, subjectstitle, subjectitem, subjects) as
(
  select reference,
    name,
    subjectstitle,
    cast(left(subjects, charindex(',',subjects+',')-1) as varchar(50)) subjectitem,
         stuff(subjects, 1, charindex(',',subjects+','), '') subjects
  from yourtable
  union all
  select reference,
    name,
    subjectstitle,
    cast(left(subjects, charindex(',',subjects+',')-1) as varchar(50)) ,
    stuff(subjects, 1, charindex(',',subjects+','), '') subjects
  from cte
  where subjects > ''
) 
select reference, name, subjectstitle, subjectitem
from cte

SQL Fiddle with Demo を参照してください

15
Taryn

これは分割関数なしで実行されます

SELECT T1.reference, T1.name, T2.my_Splits AS subjects, T1.subtitile
FROM
 (
  SELECT *,
  CAST('<X>'+replace(T.subjects,',','</X><X>')+'</X>' as XML) as my_Xml 
  FROM [yourTable] T
 ) T1
 CROSS APPLY
 ( 
 SELECT my_Data.D.value('.','varchar(50)') as my_Splits
 FROM T1.my_Xml.nodes('X') as my_Data(D)
 ) T2
9
Kaf