0

I have a MySQL table whose structure and data looks something like this:

name |       date | type  | value
-----+------------+-------+------
foo  | 2013-01-01 | blue  |     4
foo  | 2013-01-02 | green |     1
foo  | 2013-01-01 | blue  |     9
foo  | 2013-01-02 | green |     5
bar  | 2013-01-01 | blue  |    10
bar  | 2013-01-02 | green |     4
bar  | 2013-01-01 | blue  |     6
bar  | 2013-01-02 | green |     2
meow | 2013-01-01 | blue  |     5
meow | 2013-01-02 | green |     6
meow | 2013-01-01 | blue  |     4
meow | 2013-01-02 | green |     4

I'm trying to construct a query that will produce this output:

name | blue | green
-----+------+------
foo  |   13 |     6
bar  |   16 |     6
meow |    9 |    10

The name column is maintained. The blue and green columns of the output are generated based on the values of the type table column. The values of those two columns are the accumulated value of the value table column for all dates. I hope that made sense.

This is a bit out of my league when it comes to MySQL so I have no idea where to start. Is this possible using MySQL, and if so, how? For instance, how does one create output columns based on the values of a single table column?


Edit: I should specify; there is no need for this to be a single query. As long as it can be done without involving any other technologies than MySQL then I have no constraints regarding subqueries, multiple queries, views etc.

Hubro
  • 56,214
  • 69
  • 228
  • 381

6 Answers6

3

You can use CASE and SUM() if you have known number of values.

SELECT  Name,
        SUM(CASE WHEN type = 'blue' THEN value ELSE 0 END) blue,
        SUM(CASE WHEN type = 'green' THEN value ELSE 0 END) green
FROM    tableName
GROUP   BY Name

But if you have unknown number of values, you can build a dynamic query for that which yield the same result as with static query,

SELECT  GROUP_CONCAT(DISTINCT
        CONCAT('SUM(CASE WHEN type = ''',
               type,
               ''' THEN value ELSE 0 END) AS ',
               CONCAT('`', type, '`')
               )) INTO @sql
FROM TableName;

SET @sql = CONCAT('SELECT Name, ', @sql, ' 
                   FROM    tableName
                    GROUP   BY Name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
John Woo
  • 258,903
  • 69
  • 498
  • 492
1

A simple SUM with GROUP BY should solve it for you;

SELECT name, 
  SUM(CASE WHEN type='blue' THEN value ELSE 0 END) blue,
  SUM(CASE WHEN type='green' THEN value ELSE 0 END) green
FROM Table1
GROUP BY name;

An SQLfiddle to test with.

...or using somewhat briefer MySQL specific code;

SELECT name, 
  SUM(IF(type='blue', value, 0)) blue,
  SUM(IF(type='green', value, 0)) green
FROM Table1
GROUP BY name;

Another SQLfiddle.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
0

Try:

SELECT name,
    SUM(CASE WHEN type = 'blue' THEN value ELSE 0 END) AS blue,
    SUM(CASE WHEN type = 'green' THEN value ELSE 0 END) AS green
FROM yourTable
GROUP BY name

There's no PIVOT function in MySQL like there is in SQL Server for instance.

xlecoustillier
  • 16,183
  • 14
  • 60
  • 85
0

The output format is making this (unneccessary?) hard for you. A query that would give an output like this:

name | color | amount

which in your code you could easily rewrite to

name | blue | green

would that work for you?

SELECT name, color, sum(value) as amount
FROM tablename
GROUP BY name, color
Joost Pastoor
  • 253
  • 1
  • 7
0

try

SELECT name, sum(CASE type WHEN 'blue' THEN value END) blue,
             sum(CASE type WHEN 'green' THEN value END) green FROM tbl
GROUP BY name
Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
0

What you want to do is not possible in a single SQL statement from within MySQL. What you can do is create a "meta-query" which generates an sql statement which you can then prepare and execute.

Have a look at, e.g., mysql select dynamic row values as column names, another column as value

Community
  • 1
  • 1
Stefan Winkler
  • 3,871
  • 1
  • 18
  • 35