Database 如何创建在Postgresql中返回动态列名的查询?
我在一个报告数据库中有两个表,一个用于订单,另一个用于订单项。每个订单可以有多个订单项目,以及每个项目的数量:Database 如何创建在Postgresql中返回动态列名的查询?,database,postgresql,crosstab,Database,Postgresql,Crosstab,我在一个报告数据库中有两个表,一个用于订单,另一个用于订单项。每个订单可以有多个订单项目,以及每个项目的数量: Orders +----------+---------+ | order_id | email | +----------+---------+ | 1 | 1@1.com | +----------+---------+ | 2 | 2@2.com | +----------+---------+ | 3 | 3@3.com | +--
Orders
+----------+---------+
| order_id | email |
+----------+---------+
| 1 | 1@1.com |
+----------+---------+
| 2 | 2@2.com |
+----------+---------+
| 3 | 3@3.com |
+----------+---------+
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 |
+---------------+----------+----------+--------------+
出于报告目的,我希望将此数据反规范化为一个单独的PostgreSQL视图(或仅运行一个查询),该视图将上述数据转换为如下内容:
+----------+---------+-----------+-------+-----+
| order_id | email | Tee Shirt | Jeans | Hat |
+----------+---------+-----------+-------+-----+
| 1 | 1@1.com | 1 | 3 | 1 |
+----------+---------+-----------+-------+-----+
| 2 | 2@2.com | 2 | 0 | 0 |
+----------+---------+-----------+-------+-----+
| 3 | 3@3.com | 3 | 1 | 0 |
+----------+---------+-----------+-------+-----+
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
);
也就是说,它是订单中每个项目的数量加上产品名称的总和;以及设置为列标题的产品名称。我是否需要使用交叉表之类的工具来实现这一点,或者即使在查询运行之前我不知道不同产品名称的列表,是否有一种聪明的方法来使用子查询。这是一个可能的答案:
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, '1@1.com');
insert into orders VALUES (2, '2@2.com');
insert into orders VALUES (3, '3@3.com');
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 | 1@1.com | 1 | 3 | 1
2 | 2@2.com | 2 | 0 | 0
3 | 3@3.com | 3 | 1 | 0
(3 rows)
根据您的评论,您可以尝试这样使用:
+----------+---------+-----------+-------+-----+
| order_id | email | Tee Shirt | Jeans | Hat |
+----------+---------+-----------+-------+-----+
| 1 | 1@1.com | 1 | 3 | 1 |
+----------+---------+-----------+-------+-----+
| 2 | 2@2.com | 2 | 0 | 0 |
+----------+---------+-----------+-------+-----+
| 3 | 3@3.com | 3 | 1 | 0 |
+----------+---------+-----------+-------+-----+
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的一部分,应该避免 这很好,而且确实有效。但我真正想要的是这样一个查询,它可以扩展到30个产品名称,如果我不知道不同的产品名称列表,那么可以通过
从订单项中选择不同的(产品名称)这样的查询来检索产品名称,使用crosstab@Joe:你能解决问题吗?没有特别好的查询。不幸的是,我不得不在查询中列出我的每种产品。仍然在寻找使用交叉表的好方法吗