Вставить несколько строк в одну таблицу на основе номера в другой таблице
Я впервые создаю базу данных, используя 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