PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Truy vấn bảng chéo PostgreSQL

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ần
 Section | 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ần
 Section | 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 ra text , date , numeric vv cho các thuộc tính tương ứng. Có một ví dụ về mã ở cuối chương crosstab(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?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails 3.1 - Đẩy đến Heroku - Lỗi khi cài đặt bộ điều hợp postgres?

  2. Cách thoát chuỗi khi khớp mẫu trong PostgreSQL

  3. Quản lý &Giám sát Cơ sở dữ liệu cho PostgreSQL 12

  4. DROP TABLE IF EXISTS Ví dụ trong PostgreSQL

  5. Tác nhân PostgreSQL trong ủy ban tiêu chuẩn SQL một lần nữa