Transpose grouped dates with MySQL - 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)

Related

count new users by each months in sql

i am trying to count new users recorded by each month of this year.
like
Need data month wise, which is registerd by month new users
JAn Feb Mar April May ..... Dec
1 2 4 2 5 ..... 1
through created_at date and user Id.
here is user_table
id created_at
1 2020-01-09 22:38:55
2 2020-02-09 22:38:55
3 2020-02-09 22:38:55
4 2020-03-09 22:38:55
5 2020-03-09 22:38:55
6 2020-03-09 22:38:55
7 2020-04-09 22:38:55
8 2020-04-09 22:38:55
9 2020-05-09 22:38:55
i am trying with this query
SELECT ut.id, Month(FROM_UNIXTIME(ut.created_at)), Count(*)
from $userTable ut
where FROM_UNIXTIME(ut.created_at) >= CURDATE() - INTERVAL 1 YEAR
GROUP BY Month(FROM_UNIXTIME(ut.created_at));
You can group by year and sum by month like this:
select YEAR(created_at) as year,
sum(case when Month(created_at) = 1 then 1 else 0 end) AS Jan,
sum(case when Month(created_at) = 2 then 1 else 0 end) AS Feb,
sum(case when Month(created_at) = 3 then 1 else 0 end) AS Mar,
sum(case when Month(created_at) = 4 then 1 else 0 end) AS Apr,
sum(case when Month(created_at) = 5 then 1 else 0 end) AS May,
sum(case when Month(created_at) = 6 then 1 else 0 end) AS Jun,
sum(case when Month(created_at) = 7 then 1 else 0 end) AS Jul,
sum(case when Month(created_at) = 8 then 1 else 0 end) AS Aug,
sum(case when Month(created_at) = 9 then 1 else 0 end) AS Sep,
sum(case when Month(created_at) = 10 then 1 else 0 end) AS Oct,
sum(case when Month(created_at) = 11 then 1 else 0 end) AS Nov,
sum(case when Month(created_at) = 12 then 1 else 0 end) AS Dec from ut group by YEAR(created_at)
all columns that being used in the select that are not an aggregated function need to be grouped, ut.id is not group and in your case should be removed from the select
Try
SELECT Month(FROM_UNIXTIME(ut.created_at)), Count(*) from $userTable ut
where FROM_UNIXTIME(ut.created_at) >= CURDATE() - INTERVAL 1 YEAR
GROUP BY Month(FROM_UNIXTIME(ut.created_at));
If you want to mix data from this year and last year for the past 12 months, you can use:
SELECT SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 1) AS Jan,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 2) AS Feb,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 3) AS Mar,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 4) AS Apr,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 5) AS May,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 6) AS Jun,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 7) AS Jul,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 8) AS Aug,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 9) AS Sep,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 10) AS Oct,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 11) AS Nov,
SUM(MONTH(FROM_UNIXTIME(ut.created_at)) = 12) AS Dec
FROM ut
WHERE FROM_UNIXTIME(ut.created_at) >= CURDATE() - INTERVAL 1 YEAR
Note: This assumes that FROM_UNIXTIME() is a actually necessary. It also uses a convenient MySQL shortcut for conditional aggreation.

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

Converting imported dates in SQL Server 2008 to standard

I have existing dates in our database where some dates are formatted mm/dd/yyyy and others are dd/mm/yyyy. To be able to use MONTH() and YEAR() I need to convert the dates to yyyy/mm/dd but it doesn't seems like there is any easy way to do this. I've tried CONVERT() and DATEPART() with no success to convert my dates to the usable format in SQL Server 2008
My last resort is changing the 384 different dates this way.
UPDATE Hardware_RefreshData
SET InstallDate = '2014/9/9'
WHERE InstallDate = '9/9/2014
My goal is to be able to report on a specific month like this.
SELECT
InstallDate,
MONTH(InstallDate) AS Month,
YEAR(InstallDate) AS Year,
COUNT(*) AS Total
FROM
Hardware_RefreshData
GROUP BY
InstallDate
ORDER BY
YEAR(InstallDate) DESC, MONTH(InstallDate) DESC
Does anyone know of a better way to do this?
Now that we fixed the date Issue i was able to build my Query for my report
Here is what i was able to do to report on the fiscal year.
SELECT Technician, Count(*) as '2016/17 Total',
SUM(CASE WHEN DATEPART (Month, InstallDate) = 04 THEN 1 ELSE 0 END) AS Apr,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 05 THEN 1 ELSE 0 END) AS May,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 06 THEN 1 ELSE 0 END) AS Jun,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 07 THEN 1 ELSE 0 END) AS Jul,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 08 THEN 1 ELSE 0 END) AS Aug,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 09 THEN 1 ELSE 0 END) AS Sep,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 10 THEN 1 ELSE 0 END) AS Oct,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 11 THEN 1 ELSE 0 END) AS Nov,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 12 THEN 1 ELSE 0 END) AS Dec,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 01 THEN 1 ELSE 0 END) AS Jan,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 02 THEN 1 ELSE 0 END) AS Feb,
SUM(CASE WHEN DATEPART (Month, InstallDate) = 03 THEN 1 ELSE 0 END) AS Mar
FROM Hardware_RefreshData
Where InstallDate between '2016-04-01' and '2017-03-31'
GROUP BY Technician
ORDER BY Technician desc;
Thanks for the input :)

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.

Extracting Data as columns for each month using only 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