4

I am using a PostgreSQL database and have a table as follows:

--------------------------------------
| Date  | MetricType  | MetricValue  |
--------------------------------------
| date1 | MetricA     | val          |
--------------------------------------
| date1 | MetricB     | val          |
--------------------------------------
| date1 | MetricC     | val          |
--------------------------------------
| date2 | MetricA     | val          |
--------------------------------------
| date2 | MetricB     | val          |
--------------------------------------
| date2 | MetricC     | val          |
--------------------------------------

As you can see, each date has a set of metric types and each type has a value. I want to write a Select statement which combines this data in the following manor

------------------------------------------
| Date  | MetricA  | MetricB  | MetricC  | 
------------------------------------------
| date1 | val      | val      | val      |
------------------------------------------
| date2 | val      | val      | val      |
------------------------------------------

I am not sure how to go about writing this Select statement to get these results. Can anyone help?

1
  • As always the question should include your version of PostgreSQL and an exact table definition. Consider the info for the PostgreSQL tag. Commented Jan 16, 2013 at 23:20

4 Answers 4

3

This data transformation is a pivot. If your database doesn't have a pivot function, then you can use an aggregate function with a CASE expression:

select Date,
  max(case when MetricType = 'MetricA' then MetricValue end) MetricA,
  max(case when MetricType = 'MetricB' then MetricValue end) MetricB,
  max(case when MetricType = 'MetricC' then MetricValue end) MetricC
from yourtable
group by Date

See SQL Fiddle with Demo

The result is:

|  DATE | METRICA | METRICB | METRICC |
---------------------------------------
| date1 |     val |     val |     val |
| date2 |     val |     val |     val |

You can also do this using multiple joins on the table:

select a.date as Date,
 a.MetricValue as MetricA,
 b.MetricValue as MetricB,
 c.MetricValue as MetricC 
from yourtable a
left join yourtable b 
  on a.date = b.date and b.MetricType = 'MetricB'
left join yourtable c 
  on a.date = c.date and c.MetricType = 'MetricC'
where a.MetricType = 'MetricA'

See SQL Fiddle with Demo

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

Comments

3

See http://www.artfulsoftware.com/infotree/queries.php#78

For a tutorial, what you are looking for is called a "pivot" This can also be done using CASE as shown here:http://stackoverflow.com/questions/1241178/mysql-rows-to-columns

Comments

3

Actually, Postgres does have pivot functions. Install the additional module tablefunc.
Find more details and explanation under this related question:
PostgreSQL Crosstab Query

Your query could look like this. Assuming the metrics to be of data type integer:

SELECT * FROM crosstab(
   'SELECT date, metrictype, metricvalue 
    FROM   tbl
    ORDER  BY 1,2'  -- could also just be "ORDER BY 1" here

   ,$$VALUES ('MetricA'::text), ('MetricB'), ('MetricC')$$)
AS ct ("Section" text, "MetricA" int, "MetricB" int, "MetricC" int);

For simple queries a CASE statement like demonstrated by @Bluefeet will do. But this query performs much faster and is much shorter for longer lists of columns / bigger tables.

Comments

0
    select a.date as Date,
     a.metric as MetricType ,
b.metric as MetricType ,
     c.metric as MetricType 
    from (select distinct date from yourtable where metric = 'metricA')  a
    join yourtable b on a.date = b.date and b.metric = 'metricB'
    join yourtable c on a.date = c.date and c.metric = 'metricC'

Comments

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.