2016-04-13 11 views
5

私は、面倒なフラットファイルのデータソースを持っています。
SSISでグループ化されたデータをロードする方法

Country City 
U.S.  New York 
      Washington 
      Baltimore 
Canada  Toronto 
      Vancouver 

しかし、私はそれはそれはデータベースにロードされています。この形式になりたい::データはこのように、グループ化され

Country City 
U.S.  New York 
U.S.  Washington 
U.S.  Baltimore 
Canada  Toronto 
Canada  Vancouver 

誰もが前に、このような問題を満たしていますか?それに対処するアイデアがありますか?
私が今得た唯一のアイデアは、カーソルを使用することですが、それはあまりにも遅いです。
ありがとうございました!

+0

IDのような別の列がない場合、都市が属する国を特定するのに役立ちます。DBMSが必要なものを得ることは不可能です。彼らは順番に行かないので。 –

答えて

3

CHAによって答えは動作しますが、ここであなたがする必要がある場合には、別のあるだろうSSISウィットでやる一時テーブル/ステージングテーブル:

データフローは、DataFlowレベルの変数を使用するスクリプト変換によって実行できます。スクリプトの各行が来ると、[国]列の値がチェックされます。

空白でない値がある場合は、変数にその値を設定し、データフローに渡します。

国に空白の値がある場合は、それを変数の値で上書きします。これは最後に非空白の国の値になります。

編集:私はあなたのエラーメッセージを見て、(スクリプトでの作業とは対照的に、データフローツール、制御フローツール)スクリプトコンポーネントについて何か新しいことを学んだ:ReadWriteVariablesの

コレクションにのみ使用可能です PostExecuteメソッドでパフォーマンスを最大化し、 ロック競合のリスクを最小限に抑えます。したがって、各データ行を処理する際に、パッケージ変数の値 を直接インクリメントすることはできません。代わりにローカル変数の の値をインクリメントし、すべてのデータが処理された後に 変数の値をPostExecuteメソッド のローカル変数の値に設定します。また、 VariableDispenserプロパティを使用して、このトピックの後半で説明する など、この制限を回避することもできます。ただし、各行が処理されるときに変数 が直接パッケージに書き込まれると、パフォーマンスに悪影響を与え、ロック競合のリスクが高くなります。あなたはそのルートを移動する場合も、回避策変数ディスペンサーに関するより多くの情報を持っているthis MSDN article、から来ているが、どうやら私は、私はあなたがパッケージ変数の値を設定することができたときの上にあなたを欺く

スクリプトでスクリプトにローカルな変数を使用し、Post-Executeイベントハンドラで変数を変更する必要があります。この記事では、スクリプト内の変数を読み取ることができないことを意味するかどうかを知ることはできません。その場合は、可変ディスペンサーが唯一の選択肢になります。または、スクリプトで読み取り専用アクセス権を持つ別の変数を作成し、その値を式に設定して、読み書き変数の値を常に持つようにすることもできます。それはうまくいくかもしれない。

+0

ありがとうございました。あなたの考えに似ていると思うCursorを使ってみました。しかし、私は実際に20k +の行を持っているので、行ごとに実行するのは遅すぎます...... –

+0

あなたのメソッドを試しましたが、私はいつもエラーメッセージ "読み書きのためにロックされた変数のコレクションPostExecuteの外部では利用できません "。しかし、PostExecute .......変数に代入を代入していますが、何が問題になったのか分かりません。ありがとう –

+0

スクリプト内のReadWrite変数の読み込みが許可されていない可能性があります。私は私が学んだ新しい情報で私の答えを編集しました。 –

3

はい、可能です。まず、IDENTITYカラムを持つテーブルにデータをロードする必要があります。

-- drop table #t 
CREATE TABLE #t (id INTEGER IDENTITY PRIMARY KEY, 
Country VARCHAR(20), 
City VARCHAR(20)) 

INSERT INTO #t(Country, City) 
SELECT a.Country, a.City 
FROM OPENROWSET(BULK 'c:\import.txt', 
    FORMATFILE = 'c:\format.fmt', 
    FIRSTROW = 2) AS a; 

select * from #t 

結果は以下のようになります。

id   Country    City 
----------- -------------------- -------------------- 
1   U.S.     New York 
2        Washington 
3        Baltimore 
4   Canada    Toronto 
5        Vancouver 

そして今、再帰CTEの魔法のビットとあなたが不足している詳細情報を取り込むことができます。

;WITH a as(
    SELECT Country 
      ,City 
      ,ID 
    FROM #t WHERE ID = 1 
    UNION ALL 
    SELECT COALESCE(NULLIF(LTrim(#t.Country), ''),a.Country) 
      ,#t.City 
      ,#t.ID 
    FROM a INNER JOIN #t ON a.ID+1 = #t.ID 
    ) 
SELECT * FROM a 
OPTION (MAXRECURSION 0) 

結果:

Country    City     ID 
-------------------- -------------------- ----------- 
U.S.     New York    1 
U.S.     Washington   2 
U.S.     Baltimore   3 
Canada    Toronto    4 
Canada    Vancouver   5 

更新:

SELECT ID 
    , COALESCE(NULLIF(LTrim(a.Country), ''), (SELECT TOP 1 Country FROM #t t WHERE t.ID < a.ID AND LTrim(t.Country) <> '' ORDER BY t.ID DESC)) 
    , City 
FROM #t a 

はところで、あなたの入力データのフォーマットのファイルが(これであなたは試してみたい場合:

タブアレマンは、同じ結果が再帰クエリすることなく達成することができるの下に示唆したように\ IMPORT.TXT及びC以下のようなフォーマットのファイル:\ format.fmt):スクリプトは、cとして入力されたデータを保存

9.0 
    2 
    1  SQLCHAR  0  11  ""  1  Country  SQL_Latin1_General_CP1_CI_AS 
    2  SQLCHAR  0  100  "\r\n" 2  City   SQL_Latin1_General_CP1_CI_AS 
+0

ありがとう。私はあなたの考えを試みたが、それは私の場合にはうまくいかなかった。私のテーブルには実際に20k +の行があるからです。だから、 "CTEが100回以上繰り返す"のようなエラーが表示される –

+0

再帰的なCTEの代わりに自己結合を使用して、再帰の制限を回避することができます。 –

+0

ありがとう@TabAlleman。再帰なしのバージョンを含めるように私の答えを更新しました – cha

関連する問題