Question

I have some sales figures over a timeline from n+ products:

DATE         PROD    SALES
2014-01-01   Alpha   1000
2014-01-01   Alpha   2000
2014-01-01   Beta    500
2014-01-03   Alpha   4000
2014-01-03   Beta    1500
2014-01-03   Gamma   700

a) I would like to display the sums per day as stacked bar-charts over time and need this format:

DATE         ALPHA   BETA   GAMMA
2014-01-01   3000    500    0
2014-01-03   4000    1500   700

b) Furthermore it would be nice to have all fully missing dates filled with 0

DATE         ALPHA   BETA   GAMMA
2014-01-01   3000    500    0
2014-01-02   0       0      0
2014-01-03   4000    1500   700

What's the best way to do this kind of aggregation in MySQL? With sub-queries?

Was it helpful?

Solution

After researching for another 24h and thanks to the comments, here is a solution for a):

-- create the sum statement for all products
SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT CONCAT('\n
  SUM(CASE WHEN prod="', prod , '" THEN sales ELSE 0 END) AS ', prod)) 
INTO @sql
FROM productsales;
SELECT @sql;

-- embed the sum statement in the generic statement
SET @sql = CONCAT('SELECT date, ', @sql, ' FROM productsales GROUP BY date');    
SELECT @sql;

-- execute as prepared statement
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

This dynamically creates a SQL statement based on the existing products:

SELECT date, 
  SUM(CASE WHEN prod="Alpha" THEN sales ELSE 0 END) AS Alpha,
  SUM(CASE WHEN prod="Beta" THEN sales ELSE 0 END) AS Beta,
  SUM(CASE WHEN prod="Gamma" THEN sales ELSE 0 END) AS Gamma 
FROM productsales GROUP BY date 

It works in MySQL directly via command line (but not via phpMyAdmin):

+------------+-------+------+-------+
| date       | Alpha | Beta | Gamma |
+------------+-------+------+-------+
| 2014-01-01 |  3000 |  500 |     0 |
| 2014-01-03 |  4000 | 1500 |   700 |
+------------+-------+------+-------+
2 rows in set (0.00 sec)

In case someone else wants to play with it, here is the test data:

CREATE TABLE IF NOT EXISTS `productsales` (
  `date` date NOT NULL,
  `prod` varchar(16) NOT NULL,
  `sales` int(11) NOT NULL
);

INSERT INTO `productsales` (`date`, `prod`, `sales`) VALUES
('2014-01-01', 'Alpha', 1000),
('2014-01-01', 'Alpha', 2000),
('2014-01-01', 'Beta', 500),
('2014-01-03', 'Alpha', 4000),
('2014-01-03', 'Beta', 1500),
('2014-01-03', 'Gamma', 700);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top