Réponse à la question initiale
Postgres permet aux fonctions de retour d'ensemble (SRF) de multiplier les lignes. generate_series() est ton ami :
INSERT INTO b (all_names, birthday)
SELECT names, current_date -- AS birthday ??
FROM (SELECT names, generate_series(1, number) FROM a);
Depuis l'introduction de LATERAL dans Postgres 9.3 vous pouvez vous en tenir au SQL standard :le SRF se déplace depuis le SELECT au FROM liste :
INSERT INTO b (all_names, birthday)
SELECT a.names, current_date -- AS birthday ??
FROM a, generate_series(1, a.number) AS rn
LATERAL est implicite ici, comme expliqué dans le manuel :
LATERALpeut également précéder un appel de fonctionFROMélément, mais dans ce cas, il s'agit d'un mot parasite, car l'expression de la fonction peut faire référence à des éléments FROM antérieurs dans tous les cas.
Opération inverse
Ce qui précède est l'opération inverse (approximativement) d'un simple agrégat count() :
INSERT INTO a (name, number)
SELECT all_names, count(*)
FROM b
GROUP BY 1;
... qui correspond à votre question mise à jour.
Notez une différence subtile entre count(*) et count(all_names) . Le premier compte toutes les lignes, quoi qu'il arrive, tandis que le second ne compte que les lignes où all_names IS NOT NULL . Si votre colonne all_names est défini comme NOT NULL , les deux renvoient la même chose, mais count(*) est un peu plus court et plus rapide.
À propos de GROUP BY 1 :
- Instruction GROUP BY + CASE