First let me start by saying that I've done intensive research before asking here. I have a table datatable
that looks like this:
+----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| id | year | jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec |
+----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2015 | 0 | 0 | 0 | 0 | 101 | 265 | 357 | 358 | 330 | 402 | 528 | 528 |
| 2 | 2016 | 602 | 837 | 854 | 723 | 802 | 943 | 689 | 771 | 595 | 487 | 647 | 488 |
| 3 | 2017 | 553 | 556 | 598 | 518 | 632 | 696 | 522 | 634 | 562 | 379 | 542 | 448 |
| 4 | 2018 | 483 | 378 | 397 | 289 | 283 | 277 | 432 | 379 | 260 | 305 | 286 | 199 |
| 5 | 2019 | 353 | 346 | 418 | 402 | 430 | 321 | 476 | 494 | 412 | 499 | 469 | 353 |
| 6 | 2020 | 363 | 422 | 191 | 0 | 42 | 253 | 333 | 368 | 389 | 387 | 329 | 273 |
| 7 | 2021 | 276 | 254 | 356 | 352 | 324 | 291 | 325 | 376 | 355 | 384 | 326 | 265 |
| 8 | 2022 | 312 | 321 | 447 | 414 | 523 | 556 | 719 | 888 | 501 | 484 | 619 | 174 |
| 9 | 2023 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
and I need a query to make my columns (jan to dec) into rows of a months
column and the year
rows into separate columns. The result should basically look like this:
+--------+------+------+------+------+------+------+------+------+------+
| months | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 |
+--------+------+------+------+------+------+------+------+------+------+
| jan | 0 | ### | ### | ### | ### | ### | ### | ### | 0 |
| feb | 0 | ### | ### | ### | ### | ### | ### | ### | 0 |
| mar | 0 | ### | ### | ### | ### | ### | ### | ### | 0 |
| apr | 0 | ### | ### | ### | ### | ### | ### | ### | 0 |
| may | 101 | ### | ### | ### | ### | ### | ### | ### | 0 |
| jun | 265 | ### | ### | ### | ### | ### | ### | ### | 0 |
| jul | 357 | ### | ### | ### | ### | ### | ### | ### | 0 |
| aug | 358 | ### | ### | ### | ### | ### | ### | ### | 0 |
| sep | 330 | ### | ### | ### | ### | ### | ### | ### | 0 |
| oct | 402 | ### | ### | ### | ### | ### | ### | ### | 0 |
| nov | 528 | ### | ### | ### | ### | ### | ### | ### | 0 |
| dec | 528 | ### | ### | ### | ### | ### | ### | ### | 0 |
+--------+------+------+------+------+------+------+------+------+------+
###
is the corresponding mapping from the previous table. Since the original table can have n
rows, the new table must evaluate its columns dynamically.
There are many resources on the web on how to do this dynamically, however they all assume only one key-value relationship must be pivoted, which is not the case here (I need every month). I managed to put together a query for jan
:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when year = ''',
year,
''' then jan else NULL end) AS `',
year,
'`'
)
) INTO @sql
FROM
datatable;
SET @sql = CONCAT('SELECT id, ', @sql, '
FROM datatable
GROUP BY id');
PREPARE stmt FROM @sql;
EXECUTE stmt;
The above query yields this result:
+----+-------+-------+-------+-------+-------+-------+-------+-------+------+
| id | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 |
+----+-------+-------+-------+-------+-------+-------+-------+-------+------+
| 1 | 0 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | NULL | 602 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 3 | NULL | NULL | 553 | NULL | NULL | NULL | NULL | NULL | NULL |
| 4 | NULL | NULL | NULL | 483 | NULL | NULL | NULL | NULL | NULL |
| 5 | NULL | NULL | NULL | NULL | 353 | NULL | NULL | NULL | NULL |
| 6 | NULL | NULL | NULL | NULL | NULL | 363 | NULL | NULL | NULL |
| 7 | NULL | NULL | NULL | NULL | NULL | NULL | 276 | NULL | NULL |
| 8 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 312 | NULL |
| 9 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 0 |
+----+-------+-------+-------+-------+-------+-------+-------+-------+------+
This is unfortunately as far as I got after spending 10 hours today. I can't seem to figure out how to include the other months and aggregate the results.
I would really appreciate any pointers in the right direction, or simply knowing whether this is even possible at all. Thanks in advance.
id
in the output.