UNION ALL
Bạn có thể "đối chiếu" với UNION ALL
đầu tiên:
SELECT name, array_agg(c) AS c_arr
FROM (
SELECT name, id, 1 AS rnk, col1 AS c FROM tbl
UNION ALL
SELECT name, id, 2, col2 FROM tbl
ORDER BY name, id, rnk
) sub
GROUP BY 1;
Điều chỉnh để tạo ra thứ tự các giá trị mà bạn yêu cầu sau này. Hướng dẫn:
Nhấn mạnh đậm của tôi.
LATERAL
truy vấn con
với VALUES
biểu thức
LATERAL
yêu cầu Postgres 9.3 trở lên.
SELECT t.name, array_agg(c) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
CROSS JOIN LATERAL (VALUES (t.col1), (t.col2)) v(c)
GROUP BY 1;
Cùng một kết quả. Chỉ cần một lần lướt qua bảng.
Chức năng tổng hợp tùy chỉnh
Hoặc bạn có thể tạo một hàm tổng hợp tùy chỉnh như đã thảo luận trong các câu trả lời liên quan sau:
- Chọn dữ liệu vào một Mảng postgres
- Có cái gì đó giống như một hàm zip () trong PostgreSQL kết hợp hai mảng không?
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Sau đó, bạn có thể:
SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Hoặc, thường nhanh hơn, trong khi không phải là SQL tiêu chuẩn:
SELECT name, array_agg_mult(ARRAY[col1, col2]) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
GROUP BY 1;
ORDER BY id
đã thêm (có thể được thêm vào các hàm tổng hợp như vậy) đảm bảo kết quả mong muốn của bạn:
a | {1,2,3,4}
b | {5,6,7,8}
Hoặc bạn có thể quan tâm đến giải pháp thay thế này:
SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Tạo mảng 2 chiều:
a | {{1,2},{3,4}}
b | {{5,6},{7,8}}
Cái cuối cùng có thể được thay thế (và nên thay thế, vì nó nhanh hơn!) Bằng array_agg()
tích hợp sẵn trong Postgres 9.5 trở lên - với khả năng tổng hợp các mảng được bổ sung:
SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Cùng một kết quả. Hướng dẫn sử dụng:
Vì vậy, không hoàn toàn giống với hàm tổng hợp tùy chỉnh của chúng tôi array_agg_mult()
;