Reputation: 21508
How can I convert the following:
+------+---------+------+
| Date | Product | Sold |
+------+---------+------+
| 1/1 | P1 | 100 |
| 1/1 | P2 | 250 |
| 1/1 | P3 | 50 |
| 2/1 | P1 | 170 |
| 2/1 | P2 | 0 |
| 2/1 | P3 | 70 |
+------+---------+------+
Into a table like this:
+------+-----+-----+----+
| Date | P1 | P2 | P3 |
+------+-----+-----+----+
| 1/1 | 100 | 250 | 50 |
| 2/1 | 170 | 0 | 70 |
+------+-----+-----+----+
Using SQL?
I know the number of products (exactly 3).
Upvotes: 0
Views: 241
Reputation: 247650
In MySQL if you have an unknown number of columns to rotate, then you can use prepared statements and your code will look like this (See SQL Fiddle with Demo):
CREATE TABLE Table1
(`Date` datetime, `Product` varchar(7), `Sold` int)
;
INSERT INTO Table1
(`Date`, `Product`, `Sold`)
VALUES
('2001-01-01 00:00:00', 'P1', 100),
('2001-01-01 00:00:00', 'P2', 250),
('2001-01-01 00:00:00', 'P3', 50),
('2001-02-01 00:00:00', 'P1', 170),
('2001-02-01 00:00:00', 'P2', 0),
('2001-02-01 00:00:00', 'P3', 70)
;
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(case when Product = ''',
Product,
''' then sold else 0 end) AS ',
Product
)
) INTO @sql
FROM Table1;
SET @sql = CONCAT('SELECT Date, ', @sql, '
FROM table1
GROUP BY date');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Upvotes: 0
Reputation: 1183
If it is SQL Server 2005+:
SELECT
Date
, [P1]
, [P2]
, [P3]
FROM
(
SELECT
Date
, Product
, Sold
FROM
ProductSold
) AS t1
PIVOT
(
MIN(Sold)
FOR Product IN ([P1], [P2], [P3])
) AS pvt
ORDER BY
Date ASC;
Upvotes: 0
Reputation: 183241
Many DBMSes offer specific support for "pivots" or "crosstab reports", but if your DBMS does not, or if you prefer a solution that will work on a variety of DBMSes, you can write:
SELECT Date,
MIN(CASE WHEN Product = 'P1' THEN Sold END) AS "P1",
MIN(CASE WHEN Product = 'P2' THEN Sold END) AS "P2",
MIN(CASE WHEN Product = 'P3' THEN Sold END) AS "P3"
FROM ___insert_table_name_here___
GROUP
BY Date
;
Edited to add: You've now mentioned that you're using MySQL, which does not have special pivot or crosstab support, so the above the query is the way to go.
Upvotes: 5