简体   繁体   English

PostgreSQL使用交叉表进行一对多的转移

[英]PostgreSQL one to many pivot with crosstab

I am trying to build a one to many query in PostgreSQL that looks at a customer table, a transaction table and the result is a table showing which products the customer has purchased. 我正在尝试在PostgreSQL中构建一对多查询,查看客户表,事务表,结果是一个表格,显示客户已购买的产品。

table: customers
id
1
2
3
4
5

table: purchases
custid  product
1       software 1
1       software 2
3       software 2
3       software 3  
4       software 1
5       software 1
5       software 2
5       software 3

The result I want to get is: 我想得到的结果是:

custid  software1   software2   software3
1       TRUE        TRUE        NULL
3       NULL        TRUE        TRUE
4       TRUE        NULL        NULL
5       TRUE        TRUE        TRUE

From what I can tell I need to use crosstab (since postgreSQL doesn't support pivot ), but I'm not sure on the snytax. 据我所知,我需要使用crosstab (因为postgreSQL不支持pivot ),但我不确定snytax。 I'd also be fine if the output included row: 如果输出包括行,我也会没事的:

custid  software1   software2   software3
2       NULL        NULL        NULL

If its easier to do it one way or the other, it doesn't really matter. 如果它更容易以某种方式做到这一点,那真的不重要。

Ignoring customers that did not buy anything, because that's a bit shorter and faster: 忽略没有购买任何东西的顾客,因为这样会更短更快:

SELECT * FROM crosstab(
    'SELECT custid, product, true FROM purchases ORDER BY 1, 2'    
  , $$VALUES ('software 1'::text), ('software 2'), ('software 3')$$)
AS ct (custid int, software1 bool, software2 bool, software3 bool);

Details: 细节:

One minor difficulty here: you need to add the boolean value in the query, since it's not in the table. 这里有一个小难点:您需要在查询中添加boolean值,因为它不在表中。

I'm not familiar with crosstab but you can it with a group by clause and a case expression like this(only if there are only those 3 softwares, if its unlimited that this solution is no good): 我不熟悉交叉表,但你可以使用group by子句和这样的case表达式(只有当只有那3个软件时,如果它无限制,这个解决方案不好):

SELECT t.id,
       max(case when s.product = 'software 1' then true end) as software1,
       max(case when s.product = 'software 2' then true end) as software2,
       max(case when s.product = 'software 3' then true end) as software3
FROM customers t
LEFT OUTER JOIN purchases s ON(t.id = s.custid)
GROUP BY t.id

This will also include a row for the missing ID's. 这还将包含缺失ID的行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM