Svar på den ursprungliga frågan
Postgres tillåter set-returning-funktioner (SRF) för att multiplicera rader. generate_series() är din vän:
INSERT INTO b (all_names, birthday)
SELECT names, current_date -- AS birthday ??
FROM (SELECT names, generate_series(1, number) FROM a);
Sedan introduktionen av LATERAL i Postgres 9.3 du kan hålla dig till standard SQL:SRF flyttas från SELECT till FROM lista:
INSERT INTO b (all_names, birthday)
SELECT a.names, current_date -- AS birthday ??
FROM a, generate_series(1, a.number) AS rn
LATERAL är implicit här, som förklaras i manualen:
LATERALkan också föregå ett funktionsanropFROMobjekt, men i det här fallet är det ett brusord, eftersom funktionsuttrycket kan hänvisa till tidigare FRÅN-objekt i alla fall.
Omvänd funktion
Ovanstående är den omvända operationen (ungefär) av en enkel aggregerad count() :
INSERT INTO a (name, number)
SELECT all_names, count(*)
FROM b
GROUP BY 1;
... som passar din uppdaterade fråga.
Notera en subtil skillnad mellan count(*) och count(all_names) . Den förra räknar alla rader, oavsett vad, medan den senare endast räknar rader där all_names IS NOT NULL . Om din kolumn all_names definieras som NOT NULL , båda returnerar samma, men count(*) är lite kortare och snabbare.
Om GROUP BY 1 :
- GROUP BY + CASE-sats