2011-06-20 25 views
5

私はこのようなテーブルを持っている:私はパートからテーブル「部」、エクスポートデータを作成したい表の正規化(個々のレコードにコンマで区切られたフィールドをパース)

デバイス

DeviceId Parts 

1   Part1, Part2, Part3 
2   Part2, Part3, Part4 
3   Part1 

列を新しい表に追加します。私は

部品その

期待される結果の後に部品の列を削除します

PartId PartName 

    1  Part1 
    2  Part2 
    3  Part3 
    4  Part4 

DevicePart

DeviceId PartId 

    1  1 
    1  2 
    1  3 
    2  2 
    2  3 
    2  4 
    3  1 

私はカーソルを使用せずにSQL Server 2008でこれを行うことができますか?

+0

あなたがこれまでに試したが何をしています。あなたが必要とするヒントは、partID(Int、Identity(1,1))、partnameを持つテーブルであり、select distinct ...でそれに挿入されます。 – Ash

+0

私はこれまでのところカーソルを試しましたが、私は解決策が気に入らず、これを行うためのより良い方法があるはずです。 –

答えて

5

- セットアップ:

declare @Device table(DeviceId int primary key, Parts varchar(1000)) 
declare @Part table(PartId int identity(1,1) primary key, PartName varchar(100)) 
declare @DevicePart table(DeviceId int, PartId int) 

insert @Device 
values 
    (1, 'Part1, Part2, Part3'), 
    (2, 'Part2, Part3, Part4'), 
    (3, 'Part1') 

--script:

declare @DevicePartTemp table(DeviceId int, PartName varchar(100)) 

insert @DevicePartTemp 
select DeviceId, ltrim(x.value('.', 'varchar(100)')) 
from 
(
    select DeviceId, cast('<x>' + replace(Parts, ',', '</x><x>') + '</x>' as xml) XmlColumn 
    from @Device 
)tt 
cross apply 
    XmlColumn.nodes('x') as Nodes(x) 


insert @Part 
select distinct PartName 
from @DevicePartTemp 

insert @DevicePart 
select tmp.DeviceId, prt.PartId 
from @DevicePartTemp tmp 
    join @Part prt on 
     prt.PartName = tmp.PartName 

- 結果:

select * 
from @Part 

PartId  PartName 
----------- --------- 
1   Part1 
2   Part2 
3   Part3 
4   Part4 


select * 
from @DevicePart 

DeviceId PartId 
----------- ----------- 
1   1 
1   2 
1   3 
2   2 
2   3 
2   4 
3   1 
0

fn_Splitを使用して、カンマ区切り値からテーブル変数を作成してください。 これを使用して、挿入物をドライブすることができます。

EDIT:実際には、まだカーソルが必要な場合があります。この答えを残しておくと、fn_Splitが役立ちます。

+0

Lordyは、その機能を使用しないでください。それはmTVFとWHILEループを使用します。それは利用可能な最も遅いスプリッターの一つです。 –

0

デバイスごとに最大数の部品がある場合、はい、カーソルなしで行うことができますが、これはかなり複雑です。

基本的に、PartID文字列内の可能なインデックスごとにDeviceIDと1つのPartID列を持つテーブル(またはビューまたはサブクエリ)を作成します。これは、fn_splitまたは別の方法を使用してPartID列を計算列にすることで実現できます。そこから、この表の複数の自己UNIONを行います。各PartID列の自己UNIONには1つの表があります。自己UNIONの各テーブルには、テーブルのクエリの選択リストに含まれるPartID列のうちの1つのみがあります。

1

これを実行するには、カーソルを使わずにタリーテーブルが必要です。

ここで集計表を作成する手順に従ってください:Tally Tables by Jeff Moden

このスクリプトは、おそらく「使用DB」の文

を変更したいので、次にあなたが実行することができ、あなたの一時データベースにテーブルを配置します以下のスクリプトはデバイスと部品の内訳を一時テーブルに挿入するためのものです。これにより、パーツ名でパーツテーブルに参加し(IDを取得する)、新しいDevicePartテーブルに挿入することができます。

select *, 
--substring(d.parts, 1, t.n) 
substring(d.parts, t.n, charindex(', ', d.parts + ', ',t.n) - t.n) 'Part' 
into #devicesparts 
from device d 
cross join tally t 
where t.n < (select max(len(parts))+ 1 from device) 
and substring(', ' + d.parts, t.n, 1) = ', ' 
関連する問題