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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19127630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 01:07:48  来源:igfitidea点击:

Insert multiple rows in one table based on number in another table

sqlpostgresqlrelational-databasegenerate-series

提问by jO.

I am creating a database for the first time using Postgres 9.3 on MacOSX.

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

Let's say I have table Aand B. Astarts off as empty and Bas filled. I would like the number of entries in column all_namesin table Bto equal the numberfor each namesin table Alike table Bbelow. Thus namesshould contain each unique entry from all_namesand numberits count. I am not used to the syntax, yet, so I do not really know how to go about it. The birthdaycolumn is redundant.

假设我有 tableAB. A开始时空空如也B。我希望表中列all_names中的条目数B等于下表中number每个names表中的条目数。因此,应包含每个唯一的入口和计数。我还不习惯语法,所以我真的不知道如何去做。该列是多余的。ABnamesall_namesnumberbirthday

Table A

桌子 A

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

Table B

桌子 B

 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

Would this be the correct way to go about it?

这是正确的方法吗?

insert into a (names, number)
select b.all_names, count(b.all_names)
from b
group by b.all_names;

回答by Erwin Brandstetter

Answer to original question

对原始问题的回答

Postgres allows set-returning functions (SRF) to multiply rows. generate_series()is your friend:

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);

Since the introduction of LATERALin Postgres 9.3you can do stick to standard SQL: the SRF moves from the SELECTto the FROMlist:

LATERALPostgres 9.3引入以来,您可以坚持使用标准 SQL:SRF 从 移动SELECTFROM列表:

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

LATERALis implicit here, as explained in the manual:

LATERAL这里是隐含的,如手册中所述

LATERALcan also precede a function-call FROMitem, but in this case it is a noise word, because the function expression can refer to earlier FROM items in any case.

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

Reverse operation

反向操作

The above is the reverse operation (approximately) of a simple aggregate count():

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

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

... which fits your updated question.

...这适合您更新的问题。

Note a subtle difference between count(*)and count(all_names). The former counts all rows, no matter what, while the latter only counts rows where all_names IS NOT NULL. If your column all_namesis defined as NOT NULL, both return the same, but count(*)is a bit shorter and faster.

请注意count(*)和之间的细微差别count(all_names)。前者计算所有行,不管是什么,而后者只计算其中 的行all_names IS NOT NULL。如果您的列all_names定义为NOT NULL,则两者都返回相同的值,但count(*)更短且速度更快。

About GROUP BY 1:

关于GROUP BY 1