【问题标题】:postgresql: copy table1 to table2 and table3, but use returned table2 values to insert into table3postgresql:将 table1 复制到 table2 和 table3,但使用返回的 table2 值插入到 table3
【发布时间】:2018-01-22 22:59:09
【问题描述】:

我有三张桌子:

table1(id, name, foo)
表 2(ID,名称)
table3(id, id2, name, foo, bar)

我想将table1中的数据复制到表2和3,但table3.id2必须对应table2中的行。我想我需要对 RETURNING 命令做点什么,但我一直没有成功。

WITH oldstuff AS (
    SELECT name, foo, 'some value' AS bar
    FROM table1
  ),
  newstuff AS (
    INSERT INTO table2 (name)
    SELECT name FROM oldstuff
    RETURNING id AS id2 /* but i also need oldstuff.name, oldstuff.foo,and oldstuff.bar */
  )
INSERT INTO table3 (id2, name, foo, bar)
SELECT * FROM newstuff; /* I cant just do a join here because the fields arent unique */

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    从概念上讲,你会这样做:

    WITH oldstuff AS (
          SELECT name, foo, 'some value' AS bar
          FROM table1
         ),
         newstuff AS (
          INSERT INTO table2 (name)
              SELECT name
              FROM oldstuff
              RETURNING *
        )
    INSERT INTO table3 (id2, name, foo, bar)
        SELECT ns.id, ns.name, os.foo, os.bar
        FROM newstuff ns join
             oldstuff os
             on ns.name = os.name;
    

    根据您的说法,这并不完全符合您的要求,因为newstuff 中没有唯一的名称。要么为原始表生成一个唯一的 id,要么只在其中插入唯一的数据:

          INSERT INTO table2 (name)
              SELECT DISTINCT name
              FROM oldstuff
              RETURNING *;
    

    嗯。 . .可能有一种笨拙的方式:

    WITH oldstuff AS (
          SELECT name, foo, 'some value' AS bar
          FROM table1
         ),
         newstuff AS (
          INSERT INTO table2 (name)
              SELECT name
              FROM oldstuff
              RETURNING *
        )
    INSERT INTO table3 (id2, name, foo, bar)
        SELECT ns.id, ns.name, os.foo, os.bar
        FROM (SELECT ns.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) as seqnum
              FROM newstuff ns
             ) ns JOIN
             (SELECT os.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) as seqnum
              FROM oldstuff os
             ) os
             on ns.name = os.name and ns.seqnum = os.seqnum;
    

    这将适用于重复的名称,并且您在决赛桌中得到一个匹配项。

    【讨论】:

    • 谢谢!在遇到this post 后,我以稍微不同的顺序进行操作,并按 id 而不是 name 排序,以确保在 row_number 中排列正确的行
    猜你喜欢
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    相关资源
    最近更新 更多