Postgres 交叉表查询动态数据透视表

Postgres Crosstab query Dynamic pivot

有人知道如何在 Postgres 中创建以下交叉表吗?

例如我有以下 table:

Store      Month        Sales
A          Mar-2020     100
A          Feb-2020     200
B          Mar-2020     400
B          Feb-2020     500
A          Jan-2020     400
C          Apr-2020     600

我想查询 return 以下交叉表,列标题不应是硬编码值,而是反映第一个 table 的 "month" 列中的值:

Store    Jan-2020    Feb-2020    Mar-2020    Apr-2020
A        400         200         100         -
B        -           500         400         -
C        -           -           -           600

这可能吗?

尝试在 SUM() 中使用 CASE 表达式,这里是 db-fiddle.

select
    store,
    sum(case when month = 'Jan-2020' then sales end) as "Jan-2020",
    sum(case when month = 'Feb-2020' then sales end) as "Feb-2020",
    sum(case when month = 'Mar-2020' then sales end) as "Mar-2020",
    sum(case when month = 'Apr-2020' then sales end) as "Apr-2020"
from myTable
group by
   store
order by
   store

输出:

+---------------------------------------------------+
|store  Jan-2020    Feb-2020    Mar-2020    Apr-2020|
+---------------------------------------------------+
| A        400         200         100         null |
| B        null        500         400         null |
| C        null        null        null        600  |
+---------------------------------------------------+

如果要在输出中用 0 替换 null 值,请使用 coalesce()

例如

coalesce(sum(case when month = 'Jan-2020' then sales end), 0)

Postgres 确实有一个 crosstab 函数,但我认为在这种情况下使用内置的过滤功能很简单:

select store,
       sum(sales) filter (where month = 'Jan-2020') as Jan_2020,
       sum(sales) filter (where month = 'Feb-2020') as Feb_2020,
       sum(sales) filter (where month = 'Mar-2020') as Mar_2020,
       sum(sales) filter (where month = 'Apr-2020') as Apr_2020
from t
group by store
order by store;

注意:这会将 NULL 个值放在没有对应值的列中,而不是 -。如果您真的想要连字符,则需要将值转换为字符串——这似乎不必要地复杂。