2017-10-11 28 views
5

Tôi có hai bảng trong một cơ sở dữ liệu báo cáo, một cho các đơn đặt hàng và một cho các mục đặt hàng. Mỗi đơn hàng có thể có nhiều mục theo thứ tự, cùng với một số lượng cho mỗi:Làm cách nào để bạn tạo truy vấn trả về tên cột động trong Postgresql?

Orders 
+----------+---------+ 
| order_id | email | 
+----------+---------+ 
| 1  | [email protected] | 
+----------+---------+ 
| 2  | [email protected] | 
+----------+---------+ 
| 3  | [email protected] | 
+----------+---------+ 

Order Items 
+---------------+----------+----------+--------------+ 
| order_item_id | order_id | quantity | product_name | 
+---------------+----------+----------+--------------+ 
| 1    | 1  | 1  | Tee Shirt | 
+---------------+----------+----------+--------------+ 
| 2    | 1  | 3  | Jeans  | 
+---------------+----------+----------+--------------+ 
| 3    | 1  | 1  | Hat   | 
+---------------+----------+----------+--------------+ 
| 4    | 2  | 2  | Tee Shirt | 
+---------------+----------+----------+--------------+ 
| 5    | 3  | 3  | Tee Shirt | 
+---------------+----------+----------+--------------+ 
| 6    | 3  | 1  | Jeans  | 
+---------------+----------+----------+--------------+ 

Đối với mục đích báo cáo, tôi rất muốn denormalise dữ liệu này vào một cái nhìn PostgreSQL riêng biệt (hoặc chỉ cần chạy một truy vấn) có thể biến các dữ liệu phía trên vào một cái gì đó như thế này:

+----------+---------+-----------+-------+-----+ 
| order_id | email | Tee Shirt | Jeans | Hat | 
+----------+---------+-----------+-------+-----+ 
| 1  | [email protected] | 1   | 3  | 1 | 
+----------+---------+-----------+-------+-----+ 
| 2  | [email protected] | 2   | 0  | 0 | 
+----------+---------+-----------+-------+-----+ 
| 3  | [email protected] | 3   | 1  | 0 | 
+----------+---------+-----------+-------+-----+ 

tức là tổng số lượng của mỗi mục trong đơn đặt hàng với tên sản phẩm; và tên sản phẩm được đặt làm tiêu đề cột. Tôi có cần phải sử dụng một cái gì đó như crosstab để làm điều này, hoặc là có một cách thông minh bằng cách sử dụng truy vấn phụ ngay cả khi tôi không biết danh sách các tên sản phẩm riêng biệt tại trước khi chạy truy vấn.

+0

nếu tôi không biết danh sách tên sản phẩm riêng biệt, hãy sử dụng crosstab –

+0

@Joe: Bạn có thể sắp xếp sự cố không? – lakshman

+0

Không phải với một truy vấn đặc biệt tốt đẹp không may, tôi đã phải liệt kê ra mỗi sản phẩm của tôi trong truy vấn. Vẫn đang tìm kiếm một cách tốt để sử dụng crosstab cho – Joe

Trả lời

0

Đây là một câu trả lời có thể:

create table orders 
(
    orders_id int PRIMARY KEY, 
    email text NOT NULL 
); 

create table orders_items 
(
    order_item_id int PRIMARY KEY, 
    orders_id int REFERENCES orders(orders_id) NOT NULL, 
    quantity int NOT NULL, 
    product_name text NOT NULL 
); 

insert into orders VALUES (1, '[email protected]'); 
insert into orders VALUES (2, '[email protected]'); 
insert into orders VALUES (3, '[email protected]'); 

insert into orders_items VALUES (1,1,1,'T-Shirt'); 
insert into orders_items VALUES (2,1,3,'Jeans'); 
insert into orders_items VALUES (3,1,1,'Hat'); 
insert into orders_items VALUES (4,2,2,'T-Shirt'); 
insert into orders_items VALUES (5,3,3,'T-Shirt'); 
insert into orders_items VALUES (6,3,1,'Jeans'); 


select 
    orders.orders_id, 
    email, 
    COALESCE(tshirt.quantity, 0) as "T-Shirts", 
    COALESCE(jeans.quantity,0) as "Jeans", 
    COALESCE(hat.quantity, 0) as "Hats" 
from 
    orders 
    left join (select orders_id, quantity from orders_items where product_name = 'T-Shirt') 
    as tshirt ON (tshirt.orders_id = orders.orders_id) 
    left join (select orders_id, quantity from orders_items where product_name = 'Jeans') 
    as jeans ON (jeans.orders_id = orders.orders_id) 
    left join (select orders_id, quantity from orders_items where product_name = 'Hat') 
    as hat ON (hat.orders_id = orders.orders_id) 
; 

Thử nghiệm với postgresql. Kết quả:

orders_id | email | T-Shirts | Jeans | Hats 
-----------+---------+----------+-------+------ 
     1 | [email protected] |  1 |  3 | 1 
     2 | [email protected] |  2 |  0 | 0 
     3 | [email protected] |  3 |  1 | 0 
(3 rows) 

Dựa trên nhận xét của bạn, bạn có thể thử sử dụng tablefunc như thế này:

CREATE EXTENSION tablefunc; 

SELECT * FROM crosstab 
(
    'SELECT orders_id, product_name, quantity FROM orders_items ORDER BY 1', 
    'SELECT DISTINCT product_name FROM orders_items ORDER BY 1' 
) 
AS 
(
     orders_id text, 
     TShirt text, 
     Jeans text, 
     Hat text 
); 

Nhưng tôi nghĩ rằng bạn đang nghĩ một cách sai lầm về SQL. Bạn thường biết những hàng nào bạn muốn và phải nói cho nó biết SQL. "Xoay bảng" 90 độ không phải là một phần của SQL và nên tránh.

+1

Điều này thật tuyệt vời và chắc chắn hoạt động. Nhưng những gì tôi thực sự tìm kiếm là một truy vấn như thế này sẽ mở rộng lên đến ~ 30 tên sản phẩm, trong đó tên sản phẩm được truy xuất bằng truy vấn như 'select distinct (product_name) từ order_items' – Joe

Các vấn đề liên quan