0

複数行で大きな挿入ステートメントを実行したいのですが、再帰により正しいSQLステートメントを作成するのが難しくなっています。例を挙げれば説明しやすくなると思います。モデルを考えてみましょう。

車両

| id |code|モデル名|
| 1 |100|デラックス|
| 10 |100|デラックスが向上しました|
| 2 |200|標準|
| 20 |200|標準の新規|

|id|名前|
|2|赤|
|3|青|

car_colors

| id | car_id | color_id |
| 3 | 1 | 2 |
| 4 | 2 | 2 |
| 5 | 2 | 3 |

デラックスカーが追加され、その後「デラックス改良」モデルが挿入されました。同じ車(同じコード)の新バージョンです。残念ながら、John Doeはcar_colorsテーブルを更新するのを忘れていたので、同じ車のコードごとに同じ色を挿入して、そのテーブルを更新したいとします。

検討した例では、タプル「Deluxe Improvement、red」(Deluxeとdeluxe Improvementは同じコードを持ち、Deluxeは赤で使用できるため)とタプル「standardnew、red」と「standardnew、同じ理由で「黒」。

PSEUDO-CODE(非SQL)は次のようになります。all_cars_and_colors= select * from car left external join car_colors

for each(this_car:all_cars_and_colors){

    if(all_cars_and_colors.color_id does not exist){
        car_colors_to_copy = select * from car inner join car_colors where car.code=this_car.code

        for each(color_to_copy: car_colors_to_copy){
            insert into car_colors(id,car_id,color_id) VALUES (nextval('id_sequence') ,this_car.id,color_to_copy.color_id)
        }

    }
}

SQLを使用してこれをどのように解決しますか?

4

2 に答える 2

1
-- spoiler
INSERT INTO car_colors (car_id, color_id)
SELECT c1.id
        , co.color_id
FROM car c1
JOIN car c0 ON 1=1
JOIN car_colors co ON co.car_id = c0.id
WHERE c1. zname = 'Deluxe improved'
AND c0. zname = 'Deluxe'
        ;

更新:要件が変更されたように見えるので、ここに新しいものがあります。レスクへのCTE..。

DROP TABLE car ;
CREATE TABLE car
        ( id INTEGER NOT NULL PRIMARY KEY
        , zcode integer NOT NULL
        , zname varchar
        );
INSERT INTO car(id, zcode,zname) VALUES
(1 ,100 , 'Deluxe' )
,(10,100 ,'Deluxe improved' )
,(2 ,200 , 'Standard' )
,(20,200 , 'Standard new' )
        ;

DROP TABLE color ;
CREATE TABLE color
        ( id integer NOT NULL PRIMARY KEY
        , zname varchar
        );

INSERT INTO color(id,zname) VALUES
(2 ,'Red' ) , (3 ,'Blue' )
        ;

DROP TABLE car_colors;
CREATE TABLE car_colors
        ( id SERIAL NOT NULL PRIMARY KEY
        , car_id  integer NOT NULL REFERENCES car (id)
        , color_id  integer NOT NULL REFERENCES color (id)
        , UNIQUE (car_id,color_id)
        )
        ;
INSERT INTO car_colors (car_id, color_id) VALUES
  (1,2) , (2,2) , (2,3)
        ;

WITH carmap AS (
        SELECT c0.id AS orgcar
                , c1.id AS newcar
        FROM car c1
        -- This is an ugly join based on a substring
        JOIN car c0 ON c1.zname ~ c0.zname AND c1.id <> c0.id
        )
INSERT INTO car_colors (car_id, color_id)
SELECT cm.newcar
        , co.color_id
FROM carmap cm
JOIN car_colors co ON co.car_id = cm.orgcar
WHERE NOT EXISTS ( SELECT *
        FROM car_colors nx
        WHERE nx.car_id = cm.newcar
        AND nx.color_id = co.color_id
        )
        ;
于 2012-07-09T14:14:01.727 に答える
0

必要なクエリは次のようになります。

insert into car_colors(car_id, color_id)
    select <deluxe improved car id>, color_id
    from car_colors
    where car_id = <deluxe car id>

これはIDを処理しません。これは、テーブルレベルで実行する必要があるためです。id列をSERIAL列として宣言する必要があります。

新しい行が重複していることが心配な場合は、次を使用します。

insert into car_colors(car_id, color_id)
    select <deluxe improved car id>, color_id
    from car_colors cc           
    where car_id = <deluxe car id> and
          color_id not in (select color_id from car_colors where car_id = <deluxe improved car id>)
于 2012-07-09T14:12:11.753 に答える