2011-07-27 8 views
0

私は以下の表を持っています。 1つ以上の名前を持っています次の表をSQLで正規化します

Id AllNames 
1 A,B,C 
2 A,B 
3 X,Y,Z 

私は以下の正規化された方法でデータを表示したいと思います。

Id Names 
1 A 
1 B 
1 C 
2 A 
2 B 
3 X 
3 Y 
3 Z 

誰でも私がそれを解決するのに役立つでしょうか。

ありがとうございます。

+0

にストリングの先頭に1を追加する必要があります名前は?または、正しい表の設計が必要ですか? – gbn

+0

スプリット名で十分でしょう。 今後はテーブル構造を変更できます。 – Shine

+0

この記事を見るhttp://stackoverflow.com/questions/314824/t-sql-opposite-to-string-concatenation-how-to-split-string-into-multiple-recor –

答えて

1

まず、インターネット上にある100万個のSQL Serverの分割機能が必要です。

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648

CREATE FUNCTION dbo.Split 
(
    @RowData nvarchar(2000), 
    @SplitOn nvarchar(5) 
) 
RETURNS @RtnValue table 
(
    Id int identity(1,1), 
    Data nvarchar(100) 
) 
AS 
BEGIN 
    Declare @Cnt int 
    Set @Cnt = 1 

    While (Charindex(@SplitOn,@RowData)>0) 
    Begin 
     Insert Into @RtnValue (data) 
     Select 
      Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1))) 

     Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData)) 
     Set @Cnt = @Cnt + 1 
    End 

    Insert Into @RtnValue (data) 
    Select Data = ltrim(rtrim(@RowData)) 

    Return 
END 

その後、それぞれの行をループにカーソルか何かが必要になります。列を分割して、選択したテーブルに挿入します。

Declare @denorm table (
id int, 
val varchar(50) 
) 
Declare @denormCol varchar(max),@originalId int  

declare stackCursor CURSOR LOCAL FAST_FORWARD FOR 
select id,allText 
from yourTable 

FETCH NEXT FROM stackCursor 
INTO @denormCol, 
    @originalId 

WHILE @@FETCH_STATUS = 0 
    BEGIN 
     insert into @denorm 
     Select @originalId,Data 
     from dbo.Split(@denormCol,',') 
    END 
CLOSE stackCursor 
DEALLOCATE stackCursor  
0

私はオプションを愛するという理由だけで、あなたがこれを行うことが一つの他の方法は、私はそれがこのように行われますが、それは私には理にかなって見ていないCTEです。私は私と一緒にSQL Serverのを持っていない方のようではないあなたが最大再帰に実行する場合、あなたは、クエリを分割する2番目のすべての名前のケース/

with recCTE as (
    select id,substring(allNames,0,charindex(',',allNames)) name,substring(allNames,charindex(',',allNames),len(allNames)-charindex(',',allNames)) allNames 
    from yourTable 
    union all 
    select id, 
    case when charindex(',',allNames) >0 then 
    substring(allNames,0,charindex(',',allNames)) name 
    else 
    allNames name 
    end 
    ,case when charindex(',',allNames) >0 then 
    substring(allNames,charindex(',',allNames),len(allNames)-charindex(',',allNames)) allNames 
    else 
    '' 
    end 
    from recCTE 
    where allNames <> '' 
) 

select id,name 
from recCTE