Вставить несколько строк в одну таблицу на основе номера в другой таблице

Я впервые создаю базу данных, используя Postgres 9.3 на MacOSX.

Допустим, у меня есть стол A а также B, Table A начинается как пустой и Table B как заполнено. Я хотел бы, чтобы количество записей в столбце all_names в таблице B чтобы равняться number для каждого names в таблице A как стол B ниже. таким образом names должен содержать каждую уникальную запись из all_names а также number его счет. Я еще не привык к синтаксису, поэтому я не знаю, как это сделать. birthday столбец является избыточным.

names | number
-------+------------
Carl  | 3
Bill  | 4
Jen   | 2

В

 all_names | birthday
-------+------------
Carl       | 17/03/1980
Carl       | 22/08/1994
Carl       | 04/09/1951
Bill       | 02/12/2003
Bill       | 11/03/1975
Bill       | 04/06/1986
Bill       | 08/07/2005
Jen        | 05/03/2009
Jen        | 01/04/1945

ОБНОВЛЕНИЕ: это было бы правильным способом пойти об этом? insert into a (names, number) select b.all_names, count(b.all_names) from b group by b.all_names;

1 ответ

Решение

Ответ на оригинальный вопрос

Postgres позволяет функциям, возвращающим множество (SRF), умножать строки. generate_series() твой друг:

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

Тем не менее, этот синтаксис осуждается и может быть удален в будущих версиях. С момента введения LATERAL в Postgres 9.3 вы можете использовать эту более перспективную версию (SRF в FROM вместо списка в целевой список):

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

LATERAL здесь подразумевается, как объясняется в руководстве:

LATERAL также может предшествовать вызову функции FROM item, но в данном случае это слово-шум, поскольку в любом случае выражение функции может ссылаться на более ранние элементы FROM.

Обратная операция

Выше приведена обратная операция (приблизительно) простого агрегата count():

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

... который соответствует вашему обновленному вопросу.

Существует тонкая разница между count(*) а также count(all_names), Первый подсчитывает все строки, несмотря ни на что, тогда как второй подсчитывает только те строки, где all_names IS NOT NULL, Если ваша колонка all_names определяется как NOT NULL, оба возвращают то же самое, но count(*) немного короче и быстрее.

Рассмотрите этот связанный ответ для больше о GROUP BY 1:
Оператор GROUP BY + CASE

Другие вопросы по тегам