PostgreSQL行插入带有额外返回字段的CTE

时间:2014-08-08 21:52:51

标签: postgresql common-table-expression postgresql-9.3

长时间读者第一次问到这里!

在我的数据库中,我有以下(简化的)示例表和一些示例数据

create table file_zips (file_id int, zip varchar(5), total int);
create table zip_collections (id serial primary key, zips varchar(5)[]);

insert into file_zips select 1, 66211, 4;
insert into file_zips select 1, 66212, 17;

insert into file_zips select 2, 66101, 1;

insert into file_zips select 3, 66600, 2;
insert into file_zips select 3, 66601, 2;
insert into file_zips select 3, 66602, 2;

insert into file_zips select 4, 66600, 1;

我想要做的是在 zip_collections 中为 file_zip 插入一行。 zip 分组在 file_id < / em>然后创建一个新表 file_collections ,填充 file_id 和插入的行的 zip_collection_id 。它似乎很好地使用了Common Table Expression,但我还没有能够让它正常工作。

这是我试图写的内容,

with w as (
  insert into zip_collections (zips) 
  select array_agg(zip)
  from file_zips
  group by file_id
  returning id, file_id
)
select id as zip_collection_id, file_id
into file_collections
from w;

查询无法执行,我无法在插入的返回子句中包含 file_id ,因为它不是 zip_collections 的一部分。有没有办法在不将 file_id 列暂时添加到 zip_collections 的情况下撰写此查询?

以下是SQL小提示示例

的链接

http://sqlfiddle.com/#!15/e72f3/6

感谢您的时间!

编辑:我扩展了示例数据。这是我期待的输出的一些例子。

file_collections

|zip_collection_id|file_id|
|1|1|
|2|2|
|3|3|
|4|4|

zip_collections

|zip_collection_id|zips|
|1|66211,66212|
|2|66101|
|3|66600,66601,66602|
|4|66600|

2 个答案:

答案 0 :(得分:1)

documentation表示插入返回的列需要实际插入列:

  

可选的RETURNING子句使INSERT根据实际插入的每一行计算和返回值。

您可以通过以下某种方式将其加入回来,并以此方式获取file_id

with w as (
   insert into zip_collections (zips) 
   select array_agg(zip)
   from file_zips
   returning id, zips
)
select w.id as zip_collection_id, z.file_id
into file_collections
from w
left join file_zips z on w.zips[1] = z.zip
;

答案 1 :(得分:0)

我认为如果没有按文件ID分组zip,你的情况就没有意义了。所以只需添加分组,将file_id放入表'zip_collections'即可。

结构和初始

create table file_zips (file_id int, zip varchar(5), total int);
create table zip_collections (id serial primary key, zips varchar(5)[], file_id int);

insert into file_zips select 1, 66211, 4;
insert into file_zips select 1, 66212, 17;

<强> SQL:

with w as (
  insert into zip_collections (zips, file_id) 
  select array_agg(zip), file_id
  from file_zips group by file_id
  returning id, file_id
)
select id as zip_collection_id, file_id
into file_collections
from w;

select * from file_collections;