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

青春壹個敷衍的年華 提交于 2019-11-28 12:24:19
Erwin Brandstetter

Answer to original question

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

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

However, this syntax is frowned upon and may be removed in future versions. Since the introduction of LATERAL in Postgres 9.3 you can use this more future-proof version (SRF in the FROM list instead in the target list):

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 can also precede a function-call FROM item, but in this case it is a noise word, because the function expression can refer to earlier FROM items in any case.

Reverse operation

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

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

... which fits your updated question.

There is 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 slightly shorter and faster.

Consider this related answer for more about GROUP BY 1:
GROUP BY + CASE statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!