Câu trả lời cho câu hỏi ban đầu
Postgres cho phép các hàm trả về thiết lập (SRF) nhân các hàng. generate_series() là bạn của bạn:
INSERT INTO b (all_names, birthday)
SELECT names, current_date -- AS birthday ??
FROM (SELECT names, generate_series(1, number) FROM a);
Kể từ khi ra đời LATERAL trong Postgres 9.3 bạn có thể bám vào SQL tiêu chuẩn:SRF di chuyển từ SELECT đến FROM danh sách:
INSERT INTO b (all_names, birthday)
SELECT a.names, current_date -- AS birthday ??
FROM a, generate_series(1, a.number) AS rn
LATERAL là ẩn ở đây, như được giải thích trong sách hướng dẫn:
LATERALcũng có thể đứng trước một hàm gọiFROMitem, nhưng trong trường hợp này, nó là một từ nhiễu, vì biểu thức hàm có thể tham chiếu đến các mục FROM gần hơn trong bất kỳ trường hợp nào.
Thao tác ngược
Trên đây là hoạt động ngược lại (gần đúng) của một tổng hợp đơn giản count() :
INSERT INTO a (name, number)
SELECT all_names, count(*)
FROM b
GROUP BY 1;
... phù hợp với câu hỏi cập nhật của bạn.
Lưu ý sự khác biệt nhỏ giữa count(*) và count(all_names) . Cái đầu tiên đếm tất cả các hàng, không có vấn đề gì, trong khi cái sau chỉ đếm các hàng mà all_names IS NOT NULL . Nếu cột của bạn all_names được định nghĩa là NOT NULL , cả hai đều trả về như nhau, nhưng count(*) ngắn hơn và nhanh hơn một chút.
Giới thiệu về GROUP BY 1 :
- Câu lệnh GROUP BY + CASE