sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQL-別のテーブルからの選択に基づいて行を挿入し、新しく挿入された行でそのテーブルのFKを更新します

    問題を解決するにはいくつかの方法があります。

    1。一時的に列を追加する

    他の人が述べたように、簡単な方法は一時的に列reminder_idを追加することです datesetに 。元のIDsを入力します reminderから テーブル。 reminderに参加するために使用します datesetを使用 テーブル。一時列を削除します。

    2。開始が一意の場合

    startの値が 列は一意であり、reminderを結合することで余分な列なしでそれを行うことができます datesetのテーブル startのテーブル 列。

    INSERT INTO dateset (start)
    SELECT start FROM reminder;
    
    WITH
    CTE_Joined
    AS
    (
        SELECT
            reminder.id AS reminder_id
            ,reminder.dateset_id AS old_dateset_id
            ,dateset.id AS new_dateset_id
        FROM
            reminder
            INNER JOIN dateset ON dateset.start = reminder.start
    )
    UPDATE CTE_Joined
    SET old_dateset_id = new_dateset_id
    ;
    

    3。開始が一意でない場合

    この場合でも、一時的な列がなくても実行できます。主なアイデアは次のとおりです。この例を見てみましょう:

    reminderには2つの行があります 同じstartで 値とID3および7:

    reminder
    id    start         dateset_id
    3     2015-01-01    NULL
    7     2015-01-01    NULL
    

    それらをdatesetに挿入した後 、たとえば1と2などの新しいIDが生成されます。

    dateset
    id    start
    1     2015-01-01
    2     2015-01-01
    

    これらの2つの行をどのようにリンクするかは実際には重要ではありません。最終結果は

    になる可能性があります
    reminder
    id    start         dateset_id
    3     2015-01-01    1
    7     2015-01-01    2
    

    または

    reminder
    id    start         dateset_id
    3     2015-01-01    2
    7     2015-01-01    1
    

    これらのバリアントは両方とも正しいです。これにより、次の解決策が得られます。

    最初にすべての行を挿入するだけです。

    INSERT INTO dateset (start)
    SELECT start FROM reminder;
    

    startで2つのテーブルを一致/結合します それが一意ではないことを知っている列。 ROW_NUMBERを追加して、「Makeit」を一意にします 2列で結合します。クエリを短くすることは可能ですが、各ステップを明示的に説明しました:

    WITH
    CTE_reminder_rn
    AS
    (
        SELECT
            id
            ,start
            ,dateset_id
            ,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
        FROM reminder
    )
    ,CTE_dateset_rn
    AS
    (
        SELECT
            id
            ,start
            ,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
        FROM dateset
    )
    ,CTE_Joined
    AS
    (
        SELECT
            CTE_reminder_rn.id AS reminder_id
            ,CTE_reminder_rn.dateset_id AS old_dateset_id
            ,CTE_dateset_rn.id AS new_dateset_id
        FROM
            CTE_reminder_rn
            INNER JOIN CTE_dateset_rn ON 
                CTE_dateset_rn.start = CTE_reminder_rn.start AND
                CTE_dateset_rn.rn = CTE_reminder_rn.rn
    )
    UPDATE CTE_Joined
    SET old_dateset_id = new_dateset_id
    ;
    

    特にROW_NUMBERのない単純なバージョンと比較すると、コードが何をするのかが明確になっていることを願っています。 。明らかに、startであっても、複雑なソリューションは機能します はユニークですが、単純なソリューションほど効率的ではありません。

    このソリューションは、dateset このプロセスの前は空です。



    1. android.content.res.Resources $ NotFoundException:文字列リソースID#0x2データベース

    2. Access2016で分割データベースを暗号化する方法

    3. パラメータ化されたSQLクエリを休止状態にする低速でアクティブなOracleセッション

    4. URLで真のデータベースオブジェクトIDを非表示にする