3

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.

2
  • Start by reviewing other [pivot-table] Q+A
    – Rick James
    Commented Dec 18, 2022 at 6:12
  • And don't include id in the output.
    – Rick James
    Commented Dec 18, 2022 at 6:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.