2017-11-30 8 views
0

長時間リードオンリーメンバー、初めて質問アスカー...多値の文字区切りの列を複数の行に分割する方法は?

それは、私は確信しているお馴染みのようですけれども、私は、この特定の問題への答えを見つけることができます。

私は、値のセミコロンで区切られたリストを含む列を持つテーブルを持っています。この表は、そのアプリケーションに関連するサーバーとともにアプリケーションのリストです。サーバーのリストはセミコロンで区切られていますが、serverIdに分かれています; x個のサーバーのserverName - 数百のサーバーに関連付けられているアプリケーションもあれば、1つに関連付けられているアプリケーションもあれば、0に関連付けられているアプリケーションもあります。このサーバーの列は、表のIDと列としてserverIdおよびserverNameを含む各固有サーバーの行になります。また

applicationId\serverId\serverName 1\serverId1\serverName1 2\serverId2\serverName2 2\serverId3\serverName3 3\serverId1\serverName1 3\serverId5\serverName5 3\serverId8\serverName8 4\serverId9\serverName9 5\

:データは、現在この

applicationId\Servers 1\serverId1;serverName1 2\serverId2;serverName2;serverId3;serverName3 3\serverId1;serverName1;serverId5;serverName5;serverId8;serverName8 4\serverId9;serverName9 5\

のように見えます

私はこのように、APPLICATIONID、サーバID、およびserverName列を持つ新しいテーブルを作成したいのですが私はserverIdとserverNameのテーブルを持っているので、applicationIdを持つテーブルにserverIdを取得できれば便利です。

applicationId\serverId

は私だけの列を分割しようとしています ';'それは次のように非常に有用ではないの出力を生成します。

applicationId\serverColumn 1\serverId1 1\serverName1 2\serverId2 2\serverName2 2\serverId3 2\serverName3 ....

任意の助けいただければ幸いです。

+1

ここでの最大の問題は、あなたが区切られたデータを格納していることです。これで、区切られた1つのバージョンから別のバージョンに移動したいと考えています。これは良い計画ではありません。代わりにこれを正規化されたデザインに移動することを検討する必要があります。 –

+0

あなたの問題は、1対多の関係を1つのテーブルに保存していることです。この問題だけでなく、データを正規化することで修正しますが、これに関するすべての将来の問題はなくなります – GuidoG

+0

残念ながら、これは私がデータを消費できる唯一の方法です。 – MattAtWork

答えて

2

これは、最小限に抑えるためのひどいデータ構造です。しかし、Jeff Modenのスプリッターを使用することは可能です。 http://www.sqlservercentral.com/articles/Tally+Table/72993/私はあなたがスプリッタを持っていると言いますが、ループや再帰的なcteを持っている場合は、Jeff'sのようなセットベースのものを放棄する必要があります。

ここでは、彼のスプリッタを利用してこの作業を行う方法の完全な機能的な例を示します。

declare @Something table 
(
    ApplicationID int 
    , ServerInfo varchar(100)) 
insert @Something 
(
    ApplicationID 
    , ServerInfo 
) values 
(1, 'serverId1;serverName1') 
, (2, 'serverId2;serverName2;serverId3;serverName3') 
, (3, 'serverId1;serverName1;serverId5;serverName5;serverId8;serverName8') 
, (4, 'serverId9;serverName9') 
; 

with ServerIDs as 
(
    select s.ApplicationID 
     , ServerID = case when x.ItemNumber % 2 = 1 then x.Item end 
     , x.ItemNumber 
    from @Something s 
    cross apply dbo.DelimitedSplit8K(s.ServerInfo, ';') x 
    where x.ItemNumber % 2 = 1 
) 
, ServerNames as 
(
    select s.ApplicationID 
     , ServerName = case when x.ItemNumber % 2 = 0 then x.Item end 
     , x.ItemNumber 
    from @Something s 
    cross apply dbo.DelimitedSplit8K(s.ServerInfo, ';') x 
    where x.ItemNumber % 2 = 0 
) 

select si.ApplicationID 
    , si.ServerID 
    , sn.ServerName 
from ServerIDs si 
join ServerNames sn on sn.ApplicationID = si.ApplicationID and si.ItemNumber + 1 = sn.ItemNumber 

これが返されます。

ApplicationID ServerID ServerName 
1    serverId1 serverName1 
2    serverId2 serverName2 
2    serverId3 serverName3 
3    serverId1 serverName1 
3    serverId5 serverName5 
3    serverId8 serverName8 
4    serverId9 serverName9 
+0

これはトリックをした!ありがとうございました!私はモジュラス演算を使用してこの作業を行うことは考えていませんでしたが、全体的に意味があり、うまく動作します。 – MattAtWork

+1

喜んで助けた。しかし真剣に...区切られたデータを保存するよりも良いアプローチを見つけようとする。 –

関連する問題