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
Insert multiple rows in one table based on number in another table
提问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 A
and B
. A
starts off as empty and B
as filled. I would like the number of entries in column all_names
in table B
to equal the number
for each names
in table A
like table B
below. Thus names
should contain each unique entry from all_names
and number
its count. I am not used to the syntax, yet, so I do not really know how to go about it. The birthday
column is redundant.
假设我有 tableA
和B
. A
开始时空空如也B
。我希望表中列all_names
中的条目数B
等于下表中number
每个names
表中的条目数。因此,应包含每个唯一的入口和计数。我还不习惯语法,所以我真的不知道如何去做。该列是多余的。A
B
names
all_names
number
birthday
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 LATERAL
in Postgres 9.3you can do stick to standard SQL: the SRF moves from the SELECT
to the FROM
list:
自LATERAL
Postgres 9.3引入以来,您可以坚持使用标准 SQL:SRF 从 移动SELECT
到FROM
列表:
INSERT INTO b (all_names, birthday)
SELECT a.names, current_date -- AS birthday ??
FROM a, generate_series(1, a.number) AS rn
LATERAL
is implicit here, as explained in the manual:
LATERAL
这里是隐含的,如手册中所述:
LATERAL
can also precede a function-callFROM
item, 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_names
is 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
: