Extracting Data as columns for each month using only MySQL - mysql

I have a database that looks something like this:
Year Month New Visitor?
2011 Jan Yes
2011 Jan No
2012 Feb No
2012 Feb No
2012 Feb Maybe
I'd like Yes's and No's to be separate columns, per month so I can print it as a chart.I understand that to do this I'll need a result like this:
Year Month Yes No Maybe
2011 Jan 1 1 0
2012 Feb 0 2 1
How might I go about this using only MySQL?

Try:
SELECT `Year`, `Month`,
COUNT(IF (`New Visitor?` = 'Yes', 1, NULL)) AS `Yes`,
COUNT(IF (`New Visitor?` = 'No', 1, NULL)) AS `No`,
COUNT(IF (`New Visitor?` = 'Maybe', 1, NULL)) AS `Maybe`
FROM `table`
GROUP BY `Year`, `Month`;

You can use the following (See SQL Fiddle with demo):
select year, month,
sum(case when newVisitor = 'yes' then 1 else 0 end) yes,
sum(case when newVisitor = 'No' then 1 else 0 end) no,
sum(case when newVisitor = 'Maybe' then 1 else 0 end) maybe
from yourtable
group by year, month

Related

I am trying to produce seasonal averages of visibility using already calculated monthly averages, but struggling

I have 70+ years of hourly visibility data that I have already calculated into a monthly average. I now need to produce seasonal averages of DJF, MAM, JJA, SON (seasonal average meaning DEC, JAN, FEB as one average and MAR, APR, MAY, the next and so on) for each of those years. Does anyone have any suggestions as to how to go about this using MySQL Workbench?
I essentially need 4 separate columns of the above mentioned months visibility. Is there something I can do under the GROUP BY function like grouping by a set or anything else?
This is what I have used to get the monthly averages but I'm not sure how to
SELECT date, avg(lowest_visibility) FROM b16.hourly
GROUP BY year(date), month(date)
ORDER BY year(date), month(date) asc
Thanks in advance for any help!
Update: I have completed this task using pivot tables and tediously changing the cells to make sure I have the correct December in my DJF seasonal average, but I would still like any guidance how to do this again in the future.
May not be any better than the query you have (who knows?)
In query union to ignore DEC in it's year and union to a query which pushes the DEC year forward
DROP TABLE IF EXISTS T;
create table t
(dt date, val int);
insert into t values
('2019-12-01',10),
('2020-01-01',25),
('2020-06-01',10),
('2020-10-01',10),
('2020-12-01',10);
select yyyy,
sum(djfsum) / sum(djfcnt) dfj ,
sum(mamcnt) / sum(mamcnt) mam ,
sum(jjasum) / sum(jjacnt) jja ,
sum(sonsum) / sum(soncnt) son
from
(
select year(t.dt) yyyy,
sum(case when MONTH(dt) IN(1,2) then val else 0 end) djfsum,
sum(case when MONTH(dt) IN(1,2) then 1 else 0 end) djfcnt,
sum(case when MONTH(dt) IN(3,4,5) then val else 0 end) mamsum,
sum(case when MONTH(dt) IN(3,4,5) then 1 else 0 end) mamcnt,
sum(case when MONTH(dt) IN(6,7,8) then val else 0 end) jjasum,
sum(case when MONTH(dt) IN(6,7,8) then 1 else 0 end) jjacnt,
sum(case when MONTH(dt) IN(9,10,11) then val else 0 end) sonsum,
sum(case when MONTH(dt) IN(9,10,11) then 1 else 0 end) soncnt
from t
where month(dt) <> 12
group by yyyy
union
select year(dt) + 1,
sum(val) as djfsum,
sum(1) as djfcnt,
0,
0,
0,
0,
0,
0
from t
where month(dt) = 12
group by year(dt) + 1
) a
group by yyyy
;
+------+---------+------+---------+---------+
| yyyy | dfj | mam | jja | son |
+------+---------+------+---------+---------+
| 2020 | 17.5000 | NULL | 10.0000 | 10.0000 |
| 2021 | 10.0000 | NULL | NULL | NULL |
+------+---------+------+---------+---------+
2 rows in set, 4 warnings (0.002 sec)

Reading Data by Year (col) and Month(row)

I really need your help on a mysql query where I am not getting any clue.
Say I have a table with two columns:
entryDate - datetime
Recruits - int
I am trying to building a mysql query to get the output like the image. Please share the query.
You can do this with conditional aggregation and arithmetic:
select monthname(entryDate) as mon,
sum(case when year(entryDate) = 2016 then recruits else 0 end) as recruits_2016,
sum(case when year(entryDate) = 2017 then recruits else 0 end) as recruits_2017,
(sum(case when year(entryDate) = 2017 then recruits end) /
sum(case when year(entryDate) = 2017 then recruits end)
) - 1 as change
from t
where entryDate between '2016-01-01' and entryDate < '2018-01-01'
group by monthname(entryDate)
order by min(entryDate);

How to select data from table to get output in transpose or crosstab manner?

I have a table reportdata with below values :
reportdata memberCount monthname year
Assigned user 588 February 2017
Assigned user 2 January 2017
Assigned user 22 May 2017
FHD 571 February 2017
FHD 15 May 2017
ICM 1 May 2017
sortingCompleted 1 February 2017
sortingCompleted 2 May 2017
I want output like :
reportdata January February May
Assigned user 2 588 22
FHD 0 571 15
ICM 0 0 1
sortingCompleted 0 1 2
I have tried below query :
select d.reportdata,
CASE WHEN d.monthname='January' THEN d.MemberCount END AS January,
CASE WHEN d.monthname='February' THEN d.MemberCount END AS February,
CASE WHEN d.monthname='May' THEN d.MemberCount END AS May from
(
select reportdata, memberCount,monthname
from cme_report where year='2017'
) as d
Please suggest the way to get expected output. Thank is advance.
You can try the following:
SELECT
reportdata,
SUM(CASE WHEN (monthname = 'January') THEN memberCount ELSE 0 END) AS 'January',
SUM(CASE WHEN (monthname = 'February') THEN memberCount ELSE 0 END) AS 'February',
SUM(CASE WHEN (monthname = 'May') THEN memberCount ELSE 0 END) AS 'May',
FROM reportdata
WHERE year = '2017'
GROUP BY reportdata

How do I count records based on time (month, year) ?

I have a table (myItems) with an item "id" and "date". Now i want to read out, how many items there are per month (i also want to distinguish between October 2013 and October 2014).
I started with:
SELECT Count(okt.id) AS Oktober, Count(nov.id) AS November
FROM `myItems` as okt,
`myItems` as nov
WHERE (okt.date between '2013-10-01' and '2013-10-31')
OR (nov.date between '2013-11-01' and '2013-11-30')
But it prints out a ridiculously large number. What am i doing wrong?
Try this. This will divide data into months and then do the COUNT :
SELECT SUM(CASE WHEN MONTH(date) = 10 THEN 1 ELSE 0 END) AS Oktober
, SUM(CASE WHEN MONTH(date) = 11 THEN 1 ELSE 0 END) AS November
FROM `myItems`
Demo: SQL Fiddle
With YEAR integrated:
SELECT 2013 as Year
, SUM(CASE WHEN MONTH(date) = 10 THEN 1 ELSE 0 END) AS Oktober
, SUM(CASE WHEN MONTH(date) = 11 THEN 1 ELSE 0 END) AS November
FROM `myItems`
WHERE YEAR(date) = 2013
UNION ALL
SELECT 2014 as Year
, SUM(CASE WHEN MONTH(date) = 10 THEN 1 ELSE 0 END) AS Oktober
, SUM(CASE WHEN MONTH(date) = 11 THEN 1 ELSE 0 END) AS November
FROM `myItems`
WHERE YEAR(date) = 2014;
;
Demo: Fiddle
With inspiration from #user77318
SELECT YEAR(date) as Year, month(date) as month, count(id) as count
FROM myItems
GROUP BY YEAR(date), MONTH(date);
I personally recommend this, more beautiful. Then you can do all the presentation stuffs on Application Layer.
Try this. Group the result by month:
SELECT month(date) as month, count(id) as count FROM myItems WHERE date between '2013-10-01' and '2013-11-30' GROUP BY MONTH(date);
Example of output result:
Month | Count
10 | 100
11 | 200
Probably you are not using join, you are just giving the conditions. First try to join these 2 tables with the primary keys or with some unique and common data column. Then try to execute above query. Somthiong like this:-
SELECT Count(okt.id) AS Oktober, Count(nov.id) AS November
FROM `myItems` as okt,
`myItems` as nov
WHERE okt.id = nov.id
AND (okt.date between '2013-10-01' and '2013-10-31')
OR (nov.date between '2013-11-01' and '2013-11-30');
May be this is helpful for you.

Transpose grouped dates with MySQL

I have a table with column date; it contains records for some months, but not continuously.
To see which months are present (present meaning 1 or more records in a specific month), I tried to make an overview. It should be something like this:
2013 Jan Feb Mar - May Jun // etc
2012 Jan - - Apr May - // etc
I can get all first days of the present months, but am stuck in how to transpose. If I do this:
SELECT
IF (d = 1, month ,'-') AS Jan,
IF (d = 2, month ,'-') AS Feb,
IF (d = 3, month ,'-') AS Mar
FROM
(SELECT
MONTH(date) AS d,
DATE_FORMAT(date, '%Y-%m-01') AS month
FROM
table
GROUP BY
month
ORDER BY
month) m
GROUP BY YEAR(month)
If gives this as result:
Jan Feb Mar
- - Mar
- Feb -
While it should give:
Jan Feb Mar
- - Mar
Jan Feb Mar
This will let you do it without a subquery:
SELECT
MAX(CASE WHEN MONTH(date) = 1 THEN 'Jan' ELSE '-' END) AS Jan,
MAX(CASE WHEN MONTH(date) = 2 THEN 'Feb' ELSE '-' END) AS Feb,
MAX(CASE WHEN MONTH(date) = 3 THEN 'Mar' ELSE '-' END) AS Mar,
MAX(CASE WHEN MONTH(date) = 4 THEN 'Apr' ELSE '-' END) AS Apr,
MAX(CASE WHEN MONTH(date) = 5 THEN 'May' ELSE '-' END) AS May,
MAX(CASE WHEN MONTH(date) = 6 THEN 'Jun' ELSE '-' END) AS Jun,
... and so on through December
FROM table
GROUP BY YEAR(date)