Resposta à pergunta original
O Postgres permite que funções de retorno de conjunto (SRF) multipliquem linhas.
generate_series()
é seu amigo:INSERT INTO b (all_names, birthday)
SELECT names, current_date -- AS birthday ??
FROM (SELECT names, generate_series(1, number) FROM a);
Desde a introdução de
LATERAL
no Postgres 9.3 você pode manter o SQL padrão:o SRF se move do SELECT
para o 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
está implícito aqui, conforme explicado no manual:
LATERAL
também pode preceder uma chamada de funçãoFROM
item, mas neste caso é uma palavra de ruído, porque a expressão da função pode se referir a itens FROM anteriores em qualquer caso.
Operação reversa
O acima é a operação inversa (aproximadamente) de um simples agregado
count()
:INSERT INTO a (name, number)
SELECT all_names, count(*)
FROM b
GROUP BY 1;
... que se encaixa na sua pergunta atualizada.
Observe uma diferença sutil entre
count(*)
e count(all_names)
. O primeiro conta todas as linhas, não importa o que, enquanto o último conta apenas as linhas em que all_names IS NOT NULL
. Se sua coluna all_names
é definido como NOT NULL
, ambos retornam o mesmo, mas count(*)
é um pouco mais curto e rápido. Sobre
GROUP BY 1
:- GROUP BY + instrução CASE