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 :
LATERAL
peut é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