Cài đặt mô-đun bổ sung tablefunc
một lần mỗi cơ sở dữ liệu, cung cấp hàm crosstab()
. Kể từ Postgres 9.1, bạn có thể sử dụng CREATE EXTENSION
vì điều đó:
CREATE EXTENSION IF NOT EXISTS tablefunc;
Trường hợp thử nghiệm đượ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
Biểu mẫu đơ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);
Lợi nhuận:
PhầnSection | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | 7 | -- !!
- Không cần truyền và đổi tên.
- Lưu ý không chính xác kết quả cho
C
:giá trị7
được điền vào cột đầu tiên. Đôi khi, hành vi này là mong muốn, nhưng không áp dụng 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 , danh mục , giá trị . Không có chỗ cho cột phụ như trong lựa chọn thay thế 2 tham số bên dưới.
Biểu mẫu 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);
Lợi nhuận:
PhầnSection | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | | 7 -- !!
-
Lưu ý kết quả chính xác cho
C
. -
Tham số thứ hai có thể là bất kỳ truy vấn nào trả về một hàng mỗi thuộc tính khớp với thứ tự của đị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ư sau:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
Đó là trong sách hướng dẫn.
Vì bạn vẫn phải viết chính tả tất cả các cột trong danh sách định nghĩa cột (ngoại trừ crosstabN()
biến thể), thường hiệu quả hơn nếu cung cấp danh sách ngắn trong VALUES
biểu thức như được chứng minh:
$$VALUES ('Active'::text), ('Inactive')$$)
Hoặc (không có trong sách 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 việc trích dẫn dễ dàng hơn.
-
Bạn thậm chí có thể xuất các cột có khác nhau kiểu dữ liệu 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 kiểu đích. Bằng cách này, bạn có thể có các thuộc tính thuộc loại khác nhau và xuất ratext
,date
,numeric
vv cho các thuộc tính tương ứng. Có một ví dụ về mã ở cuối chươngcrosstab(text, text)
trong sách hướng dẫn.
db <> fiddle here
Ảnh hưởng của các hàng đầu vào thừa
Các hàng đầu vào thừa được xử lý theo cách khác - các hàng trùng lặp cho cùng một tổ hợp ("row_name", "category") - (section, status)
trong ví dụ trên.
1 tham số biểu mẫu điền vào các cột giá trị có sẵn từ trái sang phải. Các giá trị thừa sẽ bị loại bỏ.
Các hàng đầu vào trước đó sẽ thắng.
2 tham số biểu mẫu chỉ định mỗi giá trị đầu vào cho cột dành riêng của nó, ghi đè lên bất kỳ lần gán trước nào.
Các hàng nhập sau sẽ giành chiến thắng.
Thông thường, bạn không có bản sao để bắt đầu. Nhưng nếu bạn làm vậy, hãy cẩn thận điều chỉnh thứ tự sắp xếp theo yêu cầu của bạn - và ghi lại những gì đang xảy ra.
Hoặc nhận kết quả tùy ý nhanh chóng nếu bạn không quan tâm. Chỉ cần lưu ý về hiệu ứng.
Ví dụ nâng cao
-
Xoay vòng trên nhiều cột bằng cách sử dụng Tablefunc - cũng minh họa "cột bổ sung" đã đề cập
-
Thay thế động cho trục xoay với CASE và GROUP BY
\crosstabview
trong psql
Postgres 9,6 đã thêm lệnh meta này vào psql thiết bị đầu cuối tương tác mặc định của nó. Bạn có thể chạy truy vấn mà bạn sẽ sử dụng như crosstab()
đầu tiên và cung cấp thông số cho \crosstabview
(ngay lập tức hoặc trong bước tiếp theo). Như:
db=> SELECT section, status, ct FROM tbl \crosstabview
Kết quả tương tự như trên, nhưng đó là tính năng đại diện ở phía máy khách duy nhất. Các hàng đầu vào được xử lý hơi khác, do đó ORDER BY
không được yêu cầu. Chi tiết cho \crosstabview
trong sách hướng dẫn. Có nhiều ví dụ mã hơn ở cuối 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):
- Làm cách nào để tạo một CROSS JOIN xoay vòng trong đó định nghĩa bảng kết quả là không xác định?