2017-10-11 52 views
5

我在報告數據庫中有兩個表格,一個用於訂單,另一個用於訂單項目。每個訂單可以有多個訂單項目,爲每個數量沿:如何創建一個在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  | 
+---------------+----------+----------+--------------+ 

就報告而言,我喜歡這個數據denormalise到一個單獨的PostgreSQL視圖(或只是運行一個查詢),它可以將數據如上所示:

+----------+---------+-----------+-------+-----+ 
| 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 | 
+----------+---------+-----------+-------+-----+ 

即,它是訂單中每個項目的數量與產品名稱的總和;並將產品名稱設置爲列標題。我是否需要使用類似crosstab的方法來執行此操作,或者是否存在使用子查詢的巧妙方法,即使在查詢運行之前我不知道不同產品名稱的列表。

+0

如果我不知道不同產品名稱的列表,請使用交叉表 –

+0

@Joe:你能解決這個問題嗎? – lakshman

+0

不幸的是,我不得不列出每個產品的查詢。仍然在尋找一種使用交叉表的好方法 – Joe

回答

0

這是一個可能的答案:

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) 
; 

測試PostgreSQL的。結果:

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) 

基於您的評論,你可以嘗試使用tablefunc這樣的:

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 
); 

但我認爲你正在考慮SQL錯誤的方式。你通常知道你想要哪些行,並且必須告訴它SQL。 「旋轉表格」90度不屬於SQL,應該避免。

+1

這非常好,當然有用。但是我真正想要的是這樣一個查詢,這個查詢可以擴展到大約30個產品名稱,其中產品名稱通過一個查詢來檢索,例如'select distinct(product_name)from order_items' – Joe

相關問題