1

次のようなファイルuniversities.txtがあります。

アラバマ

エアユニバーシティ
アラバマA&M大学
アラバマ州立大学
コンコルディアカレッジ-セルマ
フォークナー大学
ハンティンドン大学
ジャクソンビル州立大学
ジャドソン大学
マイルズ大学
オークウッド大学
サムフォード大学
サウスイースタンバイブルカレッジ
サウスクリスチャン大学
スプリングヒルカレッジ
スティルマン大学
タラデガ大学
ノースアラバマ大学
サウスアラバマ大学
ウェストアラバマ大学

アラスカ

アラスカバイブルカレッジ
アラスカパシフィック大学
シェルドンジャクソン大学
アラスカ大学-アンカレッジ
アラスカ大学-フェアバンクス
アラスカ大学-南東部

アリゾナ

アッセンブリーズオブゴッドアメリカンインディアンカレッジ
アリゾナ州立大学
アリゾナ州立大学東部
アリゾナ州立大学西部
デブリー大学-フェニックス
エンブリーリドル航空大学
グランドキャニオン大学
ノースセントラル大学
北アリゾナ大学

..など。この場合、アラバマ、アラスカ、アリゾナが場所であり、その他はすべて大学です。私がやりたいのは、場所をと呼ばれるテーブルにロードしLocation、大学をと呼ばれるテーブルにロードすることですUniversity。ここIdで、テーブルのは次のようにテーブルLocationへのFKです。University

CREATE TABLE Location (
Id          SERIAL PRIMARY KEY,
Name        TEXT
);

CREATE TABLE University (
Id          SERIAL PRIMARY KEY,
Location    INTEGER REFERENCES Location (Id) NOT NULL,
Name        TEXT
);

したがって、Postgresでやりたいことは次のようなものです。

for (int i=0 until i = universities.size()  i++){
//each entry in the universities vector is a tuple with the first entry being the country/state
//and the second entry being a vector of the universities as String's
Vector tuple = (Vector)universities.get(i);
//insert into location table
String state = (String)tuple.get(0); 
Vector u = (Vector)tuple.get(1);
for(int j=0; until j =u.size(); j++){
//insert into university table with i as FK to location table

誰もがこれを行う方法を知っていますか?

4

2 に答える 2

1

これが純粋なSQLソリューションです。

COPYファイルを一時テーブルにインポートし、残りを実行するためにデータ変更CTEPostgreSQL 9.1以降が必要)を含む1つのDMLステートメントをインポートするために使用します。両方のステップで高速である必要があります。

単一のテキスト列を持つ一時テーブル(セッションの終了時に自動的に削除されます):

CREATE TEMP TABLE tmp (txt text);

ファイルからデータをインポートします。

COPY tmp FROM '/path/to/file.txt'

リモートクライアントからこれを行う場合は、代わりにpsqlのmetaコマンドを使用してください。\copy

私の解決策は、質問に表示されているデータ形式によって異なります。つまり、都市の前後に空の行があります。インポートファイルには実際の空の文字列があると思います。特別な場合を避けるために、最初の都市の前に空の文字列を含む先頭の行があることを確認してください。

行は順番に挿入されます。順序付けせずに、次のウィンドウ関数に使用します。

WITH x AS (
    SELECT txt
          ,row_number() OVER () AS rn
          ,lead(txt) OVER () = '' AND
            lag(txt) OVER () = '' AS city
    FROM   tmp                -- don't remove empty rows just yet
    ), y AS (
    SELECT txt, city
          ,sum(city::int) OVER w AS id
    FROM   x
    WHERE  txt <> ''          -- remove empty rows now
    WINDOW w AS (ORDER BY rn)
    ), l AS (
    INSERT INTO location (id, name)
    SELECT id, txt
    FROM   y
    WHERE  city
    ), u AS (
    INSERT INTO university u (location, name)
    SELECT id, txt
    FROM   y
    WHERE  NOT city
    )
SELECT setval('location_id_seq', max(id))
FROM   y;

Voilá。

  • CTExは、前後の行の空の文字列値に基づいて都市をマークします。

  • CTEyは都市の現在の合計()を追加し、それによって各都市とそのユニに対してid完全に有効なものを形成します。id

  • CTElu実行し、挿入を実行します。これは簡単です。

  • finalSELECTは、にアタッチされたシーケンスの次の値を設定しlocation.idます。使用していないため、現在の最大値に設定する必要があります。そうしないと、場所への将来のINSERTで重複キーエラーが発生します。

于 2012-05-09T00:12:49.257 に答える
1

オリジナルをテーブルに変換するのが最も安全な方法です...その後、COPYを使用してアップロードできます。

BEGIN { bl=0; body=0; header=""; } 
$0 == "" && body==1 && header!="" { header=""; body=0; bl=1; next; }
$0 == "" && body==0 { bl=1; next; }
$0 != "" && header=="" { header=$0; bl=0; next; }
$0 != "" && bl==1 && header!="" { body=1; print header, ",", $0 }

そのようなAWKは、ファイルをテーブルに変換し、それを直接psqlコピーステートメントでアップロードできます。

COPY university_data_file_table FROM awk-mashed-file;

次に、そのテーブルを個別のテーブルに変換できます。

CREATE TABLE country AS SELECT DISTINCT country FROM university_data_file_table;
CREATE TABLE university AS SELECT country.id, udft.university FROM country, university_data_file_table udft WHERE udft.country = country.country;

そのようなものは、psqlスクリプトで簡単にスクリプト化できます。私が言うように、あなたは最初の変換をしなければなりません。

于 2012-05-09T00:49:16.933 に答える