0

我想在多行上执行一个大的插入语句,但是递归使得构建正确的 SQL 语句变得困难。我相信一个例子会更容易解释。考虑模型:

|id|代号|型号名称 |
|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 是红色的)和元组“standard new, red”和“standard new,黑色”出于同样的原因。

PSEUDO-CODE (non-sql) 应该是这样的: all_cars_and_colors = select * from car left outer 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 到 resque ...

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 回答