根据另一个表中的数字在一个表中插入多行

时间:2013-10-01 23:21:59

标签: sql postgresql relational-database generate-series

我是第一次在MacOSX上使用Postgres 9.3创建数据库。

假设我有表ABTable A开头为空,Table B为空。我希望表all_names中的列B中的条目数等于表number中每个names的{​​{1}},例如表A下面。因此,B应包含namesall_names计数的每个唯一条目。我还不习惯语法,所以我真的不知道如何去做。 number列是多余的。

A

birthday

names | number
-------+------------
Carl  | 3
Bill  | 4
Jen   | 2

更新:这是正确的方法吗? all_names | birthday -------+------------ Carl | 17/03/1980 Carl | 22/08/1994 Carl | 04/09/1951 Bill | 02/12/2003 Bill | 11/03/1975 Bill | 04/06/1986 Bill | 08/07/2005 Jen | 05/03/2009 Jen | 01/04/1945

1 个答案:

答案 0 :(得分:5)

回答原始问题

Postgres允许设置返回函数(SRF)乘以行。 generate_series()是你的朋友:

INSERT INTO b (all_names, birthday)
SELECT names, current_date -- AS birthday ??
FROM (SELECT names, generate_series(1, number) FROM a);

但是,这种语法不受欢迎,可能会在将来的版本中删除。 自LATERAL in Postgres 9.3引入后,您可以使用这个更具面向未来的版本(FROM列表中的SRF,而不是目标列表中的SRF):

INSERT INTO b (all_names, birthday)
SELECT a.names, current_date -- AS birthday ??
FROM   a, generate_series(1, a.number) AS rn

LATERAL隐含在此处,正如in the manual所述:

  

LATERAL也可以在函数调用FROM项之前,但在这种情况下   它是一个干扰词,因为函数表达式可以参考   在任何情况下早于FROM项目。

反向操作

以上是简单aggregate count()的反向操作(大约):

INSERT INTO a (name, number)
SELECT all_names, count(*)
FROM   b
GROUP  BY 1;

...符合您更新的问题。

count(*)count(all_names)之间存在细微差别。前者计算所有行,无论如何,而后者仅计算all_names IS NOT NULL行。如果您的列all_names定义为NOT NULL,则两者都返回相同,但count(*)略短且更快。

请考虑此相关答案,了解有关GROUP BY 1的更多信息:
GROUP BY + CASE statement