0

With a simple table of dates and values:

+------------+-------+
| date       | count |
+------------+-------+
| 2015-01-01 | 5     |
| 2015-01-02 | 2     |
| 2015-07-02 | 20    |

How can I get a matrix of all months as columns, and days as rows, with the values, with a single MySQL query possibly using subselects and joins?

+-----+----------+----------+---------
| Day | January  | February | March...
+-----+----------+----------+---------
| 1   | 5        | 8        | 12
| 2   | 2        | 9        | 5
| 3   | 5        | 12       | 6

Is this possible, without using PHP or any other scripting tool?

This will be used to visualize trends and peaks for days of months.

10
  • What about the year? Commented Jan 11, 2017 at 6:37
  • @Shadow That's not a duplicate. This question we know quite well how many months there are in a year, well in advance of the query being written. Commented Jan 11, 2017 at 6:43
  • @lc. The answers to the duplicate question demonstrates both static and dynamic pivoting. Pls read the duplicate question first next time. Commented Jan 11, 2017 at 6:44
  • @Shadow The question does not duplicate this one, specifically in the wording "The problem is that I cannot tell how many products I will have so the column number needs to change dynamically depending on the rows in the products table". The answer does, however, indeed also answer this question, but this happens to be a first step to a bigger answer and you would have to know to pull only that specific piece out. Commented Jan 11, 2017 at 6:50
  • @lc. The answer specifically tells you which is the static and which is the dynamic part of the solution. However, if you insist, here is another one: stackoverflow.com/questions/7674786/mysql-pivot-table Here the question does not say that the number of columns is unknown. Pivot table questions in mysql are asked on a daily basis. We should not really answer exactly the same question over and over again. Commented Jan 11, 2017 at 6:57

2 Answers 2

3

What you essentially have is a pivot, and you can accomplish this with a conditional sum (i.e. a SUM with a CASE in it), grouping by the day number to get the individual rows:

select DAY(date) as Day,
       sum(case when MONTH(date) = 1 then count else 0 end) as January,
       sum(case when MONTH(date) = 2 then count else 0 end) as February,
       --...
       sum(case when MONTH(date) = 12 then count else 0 end) as December
from myTable
group by DAY(date)
Sign up to request clarification or add additional context in comments.

7 Comments

Here...have an upvote, though note that your solution would aggregate all years (since using SUM).
@TimBiegeleisen Same for you, and of course your answer assumes there should only be one row per day. So we're probably both right and both wrong at the same time.
Well I'm assuming that the count is already some aggregate for a particular day (and year). But I could be wrong.
@TimBiegeleisen That's probably a fair assumption, and what little sample result data we have does back your theory up.
This is of course a very simplified data set, but in this case count could be number of sales in an online store, based on a date. I'm not interested in the year, since I want to get average on what days and months are popular in average, and I could also add a WHERE to filter on a specific year.
|
0

If you just want a matrix for 2015, you can do a pivot query:

SELECT DATE_FORMAT(date, '%d') AS Day,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 1  THEN count END) AS January,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 2  THEN count END) AS February,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 3  THEN count END) AS March,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 4  THEN count END) AS April,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 5  THEN count END) AS May,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 6  THEN count END) AS June,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 7  THEN count END) AS July,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 8  THEN count END) AS August,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 9  THEN count END) AS September,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 10 THEN count END) AS October,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 11 THEN count END) AS November,
       MAX(CASE WHEN DATE_FORMAT(date, '%m') = 12 THEN count END) AS December
FROM yourTable
WHERE DATE_FORMAT(date, '%Y') = '2015'
GROUP BY DATE_FORMAT(col, '%d')

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.