Cài đặt mô-đun bổ sung tablefunc
một lần cho mỗi cơ sở dữ liệu, cung cấp chức năng crosstab()
. Vì Postgres 9.1, bạn có thể sử dụng CREATE EXTENSION
cho điều đó:
CREATE EXTENSION IF NOT EXISTS tablefunc;
Trường hợp kiểm tra được cải thiện
CREATE TABLE tbl (
section text
, status text
, ct integer -- "count" is a reserved word in standard SQL
);
INSERT INTO tbl VALUES
('A', 'Active', 1), ('A', 'Inactive', 2)
, ('B', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7); -- ('C', 'Active') is missing
Hình thức đơn giản - không phù hợp với các thuộc tính bị thiếu
crosstab(text)
với 1 tham số đầu vào:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- needs to be "ORDER BY 1,2" here
) AS ct ("Section" text, "Active" int, "Inactive" int);
Trả về:
Mục | Hoạt động | Không hoạt động
--------- + -------- + ----------
Một | 1 | 2
B | 4 | 5
C | 7 | - !!
- Không cần đúc và đổi tên.
- Lưu ý kết quả không chính xác cho
C
: giá trị 7
được điền cho cột đầu tiên. Đôi khi, hành vi này là mong muốn, nhưng không phải cho trường hợp sử dụng này.
- Biểu mẫu đơn giản cũng được giới hạn ở chính xác ba cột trong truy vấn đầu vào được cung cấp: row_name , category , value . Không có chỗ cho các cột thêm như trong thay thế 2 tham số bên dưới.
Hình thức an toàn
crosstab(text, text)
với 2 tham số đầu vào:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- could also just be "ORDER BY 1" here
, $$VALUES ('Active'::text), ('Inactive')$$
) AS ct ("Section" text, "Active" int, "Inactive" int);
Trả về:
Mục | Hoạt động | Không hoạt động
--------- + -------- + ----------
Một | 1 | 2
B | 4 | 5
C | | 7 - !!
Lưu ý kết quả chính xác cho C
.
Các tham số thứ hai có thể là bất kỳ truy vấn mà trở về một hàng cho mỗi thuộc tính phù hợp với thứ tự của các định nghĩa cột ở cuối. Thường thì bạn sẽ muốn truy vấn các thuộc tính riêng biệt từ bảng bên dưới như thế này:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
Đó là trong hướng dẫn.
Vì dù sao bạn cũng phải đánh vần tất cả các cột trong danh sách định nghĩa cột (ngoại trừ các biến thể được xác định trước ), nên việc cung cấp một danh sách ngắn trong một biểu thức như thể hiện là hiệu quả hơn :crosstabN()
VALUES
$$VALUES ('Active'::text), ('Inactive')$$)
Hoặc (không có trong hướng dẫn):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
Tôi đã sử dụng báo giá đô la để làm cho trích dẫn dễ dàng hơn.
Bạn thậm chí có thể xuất các cột với các loại dữ liệu khác nhau với crosstab(text, text)
- miễn là biểu diễn văn bản của cột giá trị là đầu vào hợp lệ cho loại mục tiêu. Bằng cách này bạn có thể có các thuộc tính của loại hình khác nhau và đầu ra text
, date
, numeric
vv cho các thuộc tính tương ứng. Có một ví dụ mã ở cuối chương crosstab(text, text)
trong hướng dẫn .
db <> fiddle ở đây
Ví dụ nâng cao
\crosstabview
trong psql
Postgres 9.6 bổ sung này meta-lệnh để thiết bị đầu cuối tương tác mặc định của nó psql . Bạn có thể chạy truy vấn bạn sẽ sử dụng làm crosstab()
tham số đầu tiên và đưa nó đến \crosstabview
(ngay lập tức hoặc trong bước tiếp theo). Giống:
db=> SELECT section, status, ct FROM tbl \crosstabview
Kết quả tương tự như trên, nhưng đó là một tính năng đại diện riêng cho phía khách hàng . Các hàng đầu vào được xử lý hơi khác nhau, do đó ORDER BY
không bắt buộc. Chi tiết \crosstabview
trong hướng dẫn. Có nhiều ví dụ mã ở dưới cùng của trang đó.
Câu trả lời liên quan trên dba.SE của Daniel Vérité (tác giả của tính năng psql):
Các câu trả lời được chấp nhận trước đây là lỗi thời.
Các biến thể của chức năng crosstab(text, integer)
đã lỗi thời. integer
Tham số thứ hai được bỏ qua. Tôi trích dẫn hướng dẫn hiện tại :
crosstab(text sql, int N)
...
Phiên bản lỗi thời của crosstab(text)
. Tham số N
hiện được bỏ qua, vì số lượng cột giá trị luôn được xác định bởi truy vấn gọi
Không cần đúc và đổi tên.
Nó thất bại nếu một hàng không có tất cả các thuộc tính. Xem biến thể an toàn với hai tham số đầu vào ở trên để xử lý các thuộc tính bị thiếu đúng cách.
ORDER BY
được yêu cầu ở dạng một tham số của crosstab()
. Hướng dẫn sử dụng:
Trong thực tế, truy vấn SQL phải luôn luôn chỉ định ORDER BY 1,2
để đảm bảo rằng các hàng đầu vào được sắp xếp đúng