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

时间:2016-02-16 16:05:36

标签: sql postgresql pivot crosstab

我正在尝试在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

我想得到的结果是:

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

据我所知,我需要使用crosstab(因为postgreSQL并不支持pivot),但我对snytax不确定。如果输出包含行,我也可以。

custid  software1   software2   software3
2       NULL        NULL        NULL

如果它更容易以某种方式做到这一点,它并不重要。

2 个答案:

答案 0 :(得分:2)

忽略那些没有买任何东西的顾客,因为它更短更快:

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

详细说明:

这里有一个小难点:您需要在查询中添加boolean值,因为它不在表中。

答案 1 :(得分:1)

我不熟悉交叉表,但你可以使用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

这还将包含缺失ID的行。