2016-11-18 5 views
2

나는 세 개의 테이블이 있습니다하나의 PostgreSQL 쿼리로 전체 복사본을 만드는 방법은 무엇입니까?

CREATE TABLE offers 
(
    id serial NOT NULL PRIMARY KEY, 
    title character varying(1000) NOT NULL DEFAULT ''::character varying 
); 

CREATE TABLE items 
(
    id serial NOT NULL PRIMARY KEY, 
    offer_id integer NOT NULL, 
    title character varying(1000) NOT NULL DEFAULT ''::character varying, 
    CONSTRAINT items_offer_id_fkey FOREIGN KEY (offer_id) 
     REFERENCES offers (id) 
); 

CREATE TABLE sizes 
(
    id serial NOT NULL PRIMARY KEY, 
    item_id integer NOT NULL, 
    title character varying(1000) NOT NULL DEFAULT ''::character varying, 
    CONSTRAINT sizes_item_id_fkey FOREIGN KEY (item_id) 
     REFERENCES items (id) 
); 

나는이 개 항목이 1 이벤트가 있습니다. 각 항목은 2 개 크기를 가지고

INSERT INTO offers (title) VALUES ('My Offer'); 
INSERT INTO items (offer_id, title) VALUES (1, 'First Item'); 
INSERT INTO items (offer_id, title) VALUES (1, 'Second Item'); 
INSERT INTO sizes (item_id, title) VALUES (1, 'First Size of Item #1'); 
INSERT INTO sizes (item_id, title) VALUES (1, 'Second Size of Item #1'); 
INSERT INTO sizes (item_id, title) VALUES (2, 'First Size of Item #2'); 
INSERT INTO sizes (item_id, title) VALUES (2, 'Second Size of Item #2'); 

복제 단일 쿼리의 모든 항목과 크기가 제안하는 방법이 있나요?

내가 CTE와 그것을 해결하려고 여기 내 SQL입니다 :

WITH tmp_offers AS (
    INSERT INTO offers (title) 
    SELECT title FROM offers WHERE id = 1 
    RETURNING id 
), tmp_items AS (
    INSERT INTO items (offer_id, title) 
    (SELECT (SELECT id FROM tmp_offers), title FROM items WHERE offer_id = 1) 
    RETURNING id 
) 
INSERT INTO sizes (item_id, title) 
(SELECT (SELECT id FROM tmp_items), title FROM sizes WHERE id IN (
    SELECT sizes.id FROM sizes 
    JOIN items ON items.id = sizes.item_id 
    WHERE items.offer_id = 1 
)); 

그러나 오류이 SQL 결과, 내가 해결할 수없는 :

ERROR : 하나 이상의 표현식으로 사용 된 하위 쿼리에 의해 반환 된 행

귀하의 도움을 크게 받으실 수 있습니다.

P.S. 나는 PostgreSQL 9.5를 사용합니다.

답변

3

이 작동합니다 http://rextester.com/RYQUS11008

+0

감사합니다. 이는 단순히 놀랍고 필요한만큼 정확히 작동합니다. –

+0

나는 여기에서 문제를 발견했다고 생각한다. 마지막 질의는 ** s.id에서 ** 항목을 선택하고 * items * 테이블에서 id를 선택합니다. –

+0

@IM_AG : 당신 말이 맞습니다. 이전 항목 ID와 크기 테이블의 새 항목 ID 매핑이 생각보다 간단하지 않습니다. 내 새 버전이 그것을 처리해야합니다. –

0

당신은 아주 가깝습니다. - 그리고 그들은 당신이이 목적을 위해 할 열 것으로 보인다 여기

WITH tmp_offers AS (
     INSERT INTO offers (title) 
      SELECT title FROM offers WHERE id = 1 
      RETURNING id 
    ), 
    tmp_items AS (
    INSERT INTO items (offer_id, title) 
     SELECT o.id, i.title 
     FROM items i CROSS JOIN 
      (SELECT id FROM tmp_offers) o 
     WHERE i.offer_id = 1 
     RETURNING id, title 
) 
INSERT INTO sizes (item_id, title) 
    SELECT i.id, i.title 
    FROM tmp_items i; 

큰 차이가 tmp_items 이제 두 개의 열을 가지고 있다는 것입니다 : 그것은 작업을 필요로하는 최종 쿼리입니다.

WITH tmp_offers AS (
    INSERT INTO offers (title) 
    SELECT title 
    FROM offers 
    WHERE id = 1 
    RETURNING id 
), tmp_items AS (
    INSERT INTO items (offer_id, title) 
    SELECT o.id, i.title 
    FROM items i 
     cross join tmp_offers o 
    WHERE i.offer_id = 1 
    order by i.id 
    RETURNING items.id 
), numbered_new as (
    select ti.id, 
     row_number() over (order by ti.id) as rn 
    from tmp_items ti 
), numbered_old as (
    select i.id, 
     row_number() over (order by i.id) as rn 
    from items i 
    WHERE i.offer_id = 1 
), item_mapper as (
    select n.id as new_item_id, 
     o.id as old_item_id 
    from numbered_new n 
    join numbered_old o on n.rn = o.rn 
) 
INSERT INTO sizes (item_id, title) 
select im.new_item_id, s.title 
from sizes s 
    join item_mapper im on im.old_item_id = s.item_id; 

온라인 예 :

+0

을하지만 sizes.title 값은 잘못이다. –