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:
LATERAL
cũng có thể đứng trước một hàm gọiFROM
item, 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