简体   繁体   中英

Postgres Crosstab query Dynamic pivot

Does any one know how to create the following crosstab in Postgres?

For example I have the following 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

I would like the query to return the following crosstab, the column headings should not be hardcoded values but reflect the values in "month" column from the first table:

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

Is this possible?

Try this with CASE expression inside SUM() , here is the 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

Output:

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

If you want to replace null values with 0 in the output then use coalesce()

eg

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

Postgres does have a crosstab function, but I think using the built in filtering functionality is simple in this case:

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;

Note: This puts NULL values in the columns with no corresponding value, rather than - . If you really wanted a hyphen, you would need to convert the value to a string -- and that seems needlessly complicated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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