20

I have the following brands table with total sales per month as a result of a previous query:

id date total
123 Apr-2012 100
123 Mar-2012 150
123 Jan-2012 500
987 Apr-2012 5
987 Mar-2012 0.10
987 Feb-2012 8

I am looking to achieve the following:

id Apr-2012 Mar-2012 Feb-2012 Jan-2012
123 100 150 0 500
987 5 0.10 8 0

How do I use the date values as column labels and fill in missing dates with 0 totals?

3
  • 2
    I'm not familiar with postgres, but you should probably have a look at the crosstab function: postgresql.org/docs/9.1/static/tablefunc.html Commented Apr 5, 2014 at 20:26
  • 1
    What you want is a Pivot(Crosstab for postgres) Commented Apr 5, 2014 at 20:27
  • 1
    @AntarrByrd damn, you're googling faster than I am :) Commented Apr 5, 2014 at 20:28

1 Answer 1

17

A crosstab() query for your example would look like this:

To fill in 0 for resulting NULL values (request in comment), use COALESCE():

SELECT brand_id
     , COALESCE(jan, 0) AS "Jan-2012"
     , COALESCE(feb, 0) AS "Feb-2012"
     , COALESCE(mar, 0) AS "Mar-2012"
     , COALESCE(apr, 0) AS "Apr-2012"
FROM crosstab(
       'SELECT brand_id, month, total
        FROM   brands
        ORDER  BY 1'

       ,$$VALUES ('Jan-2012'::text), ('Feb-2012'), ('Mar-2012'), ('Apr-2012')$$
 ) AS ct (
   brand_id int
 , jan numeric    -- use actual data type!
 , feb numeric
 , mar numeric
 , apr numeric);

Detailed explanation and links:

Aside: I avoided the reserved word in standard SQL "date" as column name (even if Postgres allows it).

Sign up to request clarification or add additional context in comments.

4 Comments

That's brilliant thanks. Any tip on how to fill in the blanks with 0s?
@Jamie: I added a solution for that.
Is there a way to not hardcode month names? For example get list from another query
@EugenKonkov: If you refer to output column names, that's not easily possible as SQL demands to know names and types of result columns up front. Maybe ask a question with all relevant details ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.