Calculate AVG of each Month excluding Months w/zeroes - mysql

I have the following working query that sums the length column/values for each month.
SELECT SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 1 THEN (tblcm.Lgth) ELSE 0 END) AS 'Jan',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 2 THEN (tblcm.Lgth) ELSE 0 END) AS 'Feb',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 3 THEN (tblcm.Lgth) ELSE 0 END) AS 'Mar',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 4 THEN (tblcm.Lgth) ELSE 0 END) AS 'Apr',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 5 THEN (tblcm.Lgth) ELSE 0 END) AS 'May',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 6 THEN (tblcm.Lgth) ELSE 0 END) AS 'Jun',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 7 THEN (tblcm.Lgth) ELSE 0 END) AS 'Jul',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 8 THEN (tblcm.Lgth) ELSE 0 END) AS 'Aug',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 9 THEN (tblcm.Lgth) ELSE 0 END) AS 'Sep',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 10 THEN (tblcm.Lgth) ELSE 0 END) AS 'Oct',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 11 THEN (tblcm.Lgth) ELSE 0 END) AS 'Nov',
SUM(CASE WHEN DATE_FORMAT(tblcm.omActCompDate, '%m') = 12 THEN (tblcm.Lgth) ELSE 0 END) AS 'Dec',
SUM(tblcm.Lgth) AS Total
giving me the following:
Jan 13050
Feb 5200
Mar 48450
Apr 34041
May 38000
Jun 0
Jul 0
Aug 0
Sep 0
Oct 0
Nov 0
Dec 0
How can I get the AVG of only the months greater than zero?
I tried: avg(nullif(tblcm.Lgth, 0)) as m_Avg but get 1825
I also tried: avg(case when tblcm.Lgth = 0 then null else tblcm.Lgth end) as m_Avg but also get 1825
I need to get 27748 (which is the SUM of Jan thru May totals, divided by 5 months)

I'm pretty sure that you'll need a subquery to do that. The following assumes that your original query is correct as posted and functions as you said. This is untested, and your probably could have included some more details in your question, so let me now if this doesn't suit your needs.
SELECT AVG(sumLgth) AS avgLgth, SUM(sumLgth) AS totalLgth,
SUM(CASE WHEN theMonth = 1 THEN (tbl.sumLgth) ELSE 0 END) AS 'Jan',
SUM(CASE WHEN theMonth = 2 THEN (tbl.sumLgth) ELSE 0 END) AS 'Feb',
...
FROM (
SELECT MONTH(omActCompDate) AS theMonth, SUM(lgth) AS sumLgth
FROM tblcm
GROUP BY MONTH(omActCompDate)
HAVING sumLgth > 0
) tbl

Related

SQL grouping: Creating monthly columns with grouped data

I have the following mySQL query which generates a table listing the individual failure data and groups by the month and frequency of different types of failures.
SELECT (CASE WHEN MONTH(runtable.time) = 1 THEN 'Jan'
WHEN MONTH(runtable.time) = 2 THEN 'FEB'
WHEN MONTH(runtable.time) = 3 THEN 'MAR'
WHEN MONTH(runtable.time) = 4 THEN 'APR'
WHEN MONTH(runtable.time) = 5 THEN 'MAY'
WHEN MONTH(runtable.time) = 6 THEN 'JUN'
WHEN MONTH(runtable.time) = 7 THEN 'JUL'
WHEN MONTH(runtable.time) = 8 THEN 'AUG'
WHEN MONTH(runtable.time) = 9 THEN 'SEP'
WHEN MONTH(runtable.time) = 10 THEN 'OCT'
WHEN MONTH(runtable.time) = 11 THEN 'NOV'
WHEN MONTH(runtable.time) = 12 THEN 'DEC'
ELSE 'Error' END) as date_month, runtable.operation, pareto.failure
FROM runtable
JOIN pareto ON pareto.run_id = runtable.id
WHERE runtable.time BETWEEN '2016-01-01 00:00:00' AND '2016-12-13 23:59:59'
AND runtable.operation IN ('d','hr')
GROUP BY MONTH(runtable.time), pareto.failure
ORDER BY MONTH(runtable.time) desc, n desc;
I would like to be able to have the months as separate columns in in the table along with the total for the year, but am unaware of how to do this. My current issue is the only way I have tried of doing this involves using sum or case for each month but then I am unable to group the count of different failure types together for each month.
The way is exactly what you described: you need to use CASE WHEN and SUM functions to solve this. Take a look at this thread:
how to select 2 table like this
By the way, you have easier ways to describe months without a case function as your example code. Take a look:
MySQL DATE_FORMAT() Function
Something like: select DATE_FORMAT(now(),'%m')
I didn't understand your problem with the error column. Be specify what problems are you run into.
Good luck!
As far as I understand you're looking for the sum(pareto.failues) by month of each operation.
Check it here: http://rextester.com/MTDK27603
SELECT
runtable.operation,
pareto.failure,
COUNT(CASE WHEN MONTH(runtable.time) = 1 THEN 1 else NULL end) as 'Jan',
COUNT(CASE WHEN MONTH(runtable.time) = 2 THEN 1 else NULL end) as 'Feb',
COUNT(CASE WHEN MONTH(runtable.time) = 3 THEN 1 else NULL end) as 'Mar',
COUNT(CASE WHEN MONTH(runtable.time) = 4 THEN 1 else NULL end) as 'Apr',
COUNT(CASE WHEN MONTH(runtable.time) = 5 THEN 1 else NULL end) as 'May',
COUNT(CASE WHEN MONTH(runtable.time) = 6 THEN 1 else NULL end) as 'Jun',
COUNT(CASE WHEN MONTH(runtable.time) = 7 THEN 1 else NULL end) as 'Jul',
COUNT(CASE WHEN MONTH(runtable.time) = 8 THEN 1 else NULL end) as 'Aug',
COUNT(CASE WHEN MONTH(runtable.time) = 9 THEN 1 else NULL end) as 'Sep',
COUNT(CASE WHEN MONTH(runtable.time) = 10 THEN 1 else NULL end) as 'Oct',
COUNT(CASE WHEN MONTH(runtable.time) = 11 THEN 1 else NULL end) as 'Nov',
COUNT(CASE WHEN MONTH(runtable.time) = 12 THEN 1 else NULL end) as 'Dec',
COUNT(pareto.failure) as 'Total year'
FROM
runtable
JOIN pareto
ON pareto.run_id = runtable.id
WHERE
runtable.time BETWEEN '2016-01-01 00:00:00' AND '2016-12-13 23:59:59'
AND runtable.operation IN ('d','hr')
GROUP BY
runtable.operation, pareto.failure
;

Get Data for Grouping all Months in a year using MySql and DB2

below is my query
SELECT DISTINCT e2.status as status, e2.year as year, e2.month as month,e2.Jan,e2.Feb,e2.Mar,e2.Apr,e2.May,e2.Jun,e2.Jul,e2.Aug,e2.Sep,e2.Oct,e2.Nov, e2.Dece, e2.countTotal FROM tranx_history e1 INNER JOIN (
SELECT YEAR(e.create_dt) AS year, MONTH(e.create_dt) AS month,
SUM(CASE WHEN MONTH(e.create_dt) = 01 THEN 1 ELSE 0 END) AS Jan,
SUM(CASE WHEN MONTH(e.create_dt) = 02 THEN 1 ELSE 0 END) AS Feb,
SUM(CASE WHEN MONTH(e.create_dt) = 03 THEN 1 ELSE 0 END) AS Mar,
SUM(CASE WHEN MONTH(e.create_dt) = 04 THEN 1 ELSE 0 END) AS Apr,
SUM(CASE WHEN MONTH(e.create_dt) = 05 THEN 1 ELSE 0 END) AS May,
SUM(CASE WHEN MONTH(e.create_dt) = 06 THEN 1 ELSE 0 END) AS Jun,
SUM(CASE WHEN MONTH(e.create_dt) = 07 THEN 1 ELSE 0 END) AS Jul,
SUM(CASE WHEN MONTH(e.create_dt) = 08 THEN 1 ELSE 0 END) AS Aug,
SUM(CASE WHEN MONTH(e.create_dt) = 09 THEN 1 ELSE 0 END) AS Sep,
SUM(CASE WHEN MONTH(e.create_dt) = 10 THEN 1 ELSE 0 END) AS Oct,
SUM(CASE WHEN MONTH(e.create_dt) = 11 THEN 1 ELSE 0 END) AS Nov,
SUM(CASE WHEN MONTH(e.create_dt) = 12 THEN 1 ELSE 0 END) AS Dece,
SUM(CASE WHEN MONTH(e.create_dt) >= 01 AND MONTH(e.create_dt) <= 12 THEN 1 ELSE 0 END) as countTotal,
e.trnx_status as status
from tranx_history e
GROUP BY e.trnx_status, MONTH(e.create_dt),YEAR(e.create_dt) ) e2 ON YEAR(e1.create_dt) = e2.year AND MONTH(e1.create_dt) = e2.month ORDER BY e2.year asc, e2.month asc
For the Above query, The Output we are getting is first it is grouping by Jan then in the next row it is grouping by Feb even though status and year are same
i want the output Jan and Feb with same status and year in a single row not in different rows

MySQL select by month returns NULL for all months

Using MySQL 5.6 I am trying to select the total inspections for each month in the past 12 months with an output of 0 if there are none. I appear to be missing something here as the output is all NULL. The date_inspected field is just a regular SQL date
From what I understood, the structure should be [conditional statement, output variable, default value] but even the 0 gets ignored in favor of NULL. I am trying to understand what I am doing wrong here.
Table:
Column Type Null
id int(11) No
inspector_id int(11) Yes
company_id int(11) Yes
date_inspected date No
start_time datetime No
end_time datetime No
Query:
SELECT
SUM(IF(MONTH = 'Jan', total, 0)) AS 'Januari',
SUM(IF(MONTH = 'Feb', total, 0)) AS 'Februari',
SUM(IF(MONTH = 'Mar', total, 0)) AS 'Maart',
SUM(IF(MONTH = 'Apr', total, 0)) AS 'April',
SUM(IF(MONTH = 'May', total, 0)) AS 'Mei',
SUM(IF(MONTH = 'Jun', total, 0)) AS 'Juni',
SUM(IF(MONTH = 'Jul', total, 0)) AS 'Juli',
SUM(IF(MONTH = 'Aug', total, 0)) AS 'Augustus',
SUM(IF(MONTH = 'Sep', total, 0)) AS 'September',
SUM(IF(MONTH = 'Oct', total, 0)) AS 'Oktober',
SUM(IF(MONTH = 'Nov', total, 0)) AS 'November',
SUM(IF(MONTH = 'Dec', total, 0)) AS 'December',
SUM(total) AS all_months
FROM (
SELECT MONTH(date_inspected) AS MONTH, COUNT(*) AS total
FROM inspection
WHERE date_inspected BETWEEN NOW() AND Date_add(NOW(), interval - 12 month)
GROUP BY MONTH
) AS SubTable
Output
{ ["Januari"]=> NULL
["Februari"]=> NULL
["Maart"]=> NULL
["April"]=> NULL
["Mei"]=> NULL
["Juni"]=> NULL
["Juli"]=> NULL
["Augustus"]=> NULL
["September"]=> NULL
["Oktober"]=> NULL
["November"]=> NULL
["December"]=> NULL
["all_months"]=> NULL }
Update:
SOLUTION by Gordon Linoff
SELECT
SUM(CASE WHEN MONTH(date_inspected) = 1 THEN 1 ELSE 0 END) AS 'Januari',
SUM(CASE WHEN MONTH(date_inspected) = 2 THEN 1 ELSE 0 END) AS 'Februari',
SUM(CASE WHEN MONTH(date_inspected) = 3 THEN 1 ELSE 0 END) AS 'Maart',
SUM(CASE WHEN MONTH(date_inspected) = 4 THEN 1 ELSE 0 END) AS 'April',
SUM(CASE WHEN MONTH(date_inspected) = 5 THEN 1 ELSE 0 END) AS 'Mei',
SUM(CASE WHEN MONTH(date_inspected) = 6 THEN 1 ELSE 0 END) AS 'Juni',
SUM(CASE WHEN MONTH(date_inspected) = 7 THEN 1 ELSE 0 END) AS 'Juli',
SUM(CASE WHEN MONTH(date_inspected) = 8 THEN 1 ELSE 0 END) AS 'Augustus',
SUM(CASE WHEN MONTH(date_inspected) = 9 THEN 1 ELSE 0 END) AS 'September',
SUM(CASE WHEN MONTH(date_inspected) = 10 THEN 1 ELSE 0 END) AS 'Oktober',
SUM(CASE WHEN MONTH(date_inspected) = 11 THEN 1 ELSE 0 END) AS 'November',
SUM(CASE WHEN MONTH(date_inspected) = 12 THEN 1 ELSE 0 END) AS 'December'
FROM inspection
WHERE date_inspected BETWEEN Date_add(NOW(), interval - 12 month) AND NOW()
As I understand it, we've given the SUM() a conditional CASE statement that if the current record's date_inspected's MONTH is equal to the MySQL constant for that value, return true and add it to the total, else do nothing.
More on MySQL CASE
between must use the smaller value first and not the other way around. Change
BETWEEN NOW() AND Date_add(NOW(), interval - 12 month)
to
BETWEEN Date_add(NOW(), interval - 12 month) and NOW()
And month() returns a number of the month and not the name.
Juergen is correct on one problem in your query. Another is that MONTH() returns a number, not a string.
And, you can further simplify the query. A subquery is not needed:
SELECT SUM(CASE WHEN MONTH(date_inspected) = 1 THEN 1 ELSE 0 END)) AS 'Januari',
SUM(CASE WHEN MONTH(date_inspected) = 2 THEN 1 ELSE 0 END)) AS 'Februari',
. . .
FROM inspection
WHERE date_inspected BETWEEN Date_add(NOW(), interval - 12 month) AND NOW();

SQL - Make a custom table with month based columns and year based rows

I am trying to make an awesome custom table which counts the amount of rows and organises them so that if there are three rows with a date in January 2013, four in March 2014 and five in October 2014 the table would show up as:
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2013 3 0 0 0 0 0 0 0 0 0 0 0
2014 0 0 4 0 0 0 0 0 0 5 0 0
I would recommend using a view, rather than a new table, this way when your underlying data changes your new table won't be out of sync.
Since you have not given much sample data I have had to assume a structure, but you would want something like this:
CREATE TABLE T (`Date` DATETIME);
INSERT T (`Date`)
VALUES
('2013-01-01'), ('2013-01-02'), ('2013-01-03'),
('2014-03-01'), ('2014-03-02'), ('2014-03-03'),
('2014-10-01'), ('2014-10-01'), ('2014-10-01'),
('2014-10-01'), ('2014-10-01');
CREATE VIEW V
AS
SELECT YEAR(`Date`) AS `Year`,
COUNT(CASE WHEN MONTH(`Date`) = 1 THEN 1 END) AS `Jan`,
COUNT(CASE WHEN MONTH(`Date`) = 2 THEN 1 END) AS `Feb`,
COUNT(CASE WHEN MONTH(`Date`) = 3 THEN 1 END) AS `Mar`,
COUNT(CASE WHEN MONTH(`Date`) = 4 THEN 1 END) AS `Apr`,
COUNT(CASE WHEN MONTH(`Date`) = 5 THEN 1 END) AS `May`,
COUNT(CASE WHEN MONTH(`Date`) = 6 THEN 1 END) AS `Jun`,
COUNT(CASE WHEN MONTH(`Date`) = 7 THEN 1 END) AS `Jul`,
COUNT(CASE WHEN MONTH(`Date`) = 8 THEN 1 END) AS `Aug`,
COUNT(CASE WHEN MONTH(`Date`) = 9 THEN 1 END) AS `Sep`,
COUNT(CASE WHEN MONTH(`Date`) = 10 THEN 1 END) AS `Oct`,
COUNT(CASE WHEN MONTH(`Date`) = 11 THEN 1 END) AS `Nov`,
COUNT(CASE WHEN MONTH(`Date`) = 12 THEN 1 END) AS `Dec`
FROM T
GROUP BY YEAR(`Date`);
Example on SQL Fiddle

Mysql Case - Count Fields thats fall in curtain hours

I am trying to set up a report that has the following fields :
Pretty much need the report to show the date, the total records that fall with in that date (so I group by Date) and then on a per hour basis for a 12 hour work day (from 8AM - 8PM) I need to count when a records is present within those times. After some brain storming and brain farts I thought why not use a case. This is what I have tried :
SELECT
DATE_FORMAT(signintime, '%b %d, %Y') Date,
COUNT(session_id) as Total,
SUM(CASE WHEN HOUR(signintime) > 08 AND HOUR(signintime) < 09 THEN 1 ELSE 0 END) '8AM-9PM',
SUM(CASE WHEN HOUR(signintime) > 09 AND HOUR(signintime) < 10 THEN 1 ELSE 0 END) '9AM-10AM',
SUM(CASE WHEN HOUR(signintime) > 10 AND HOUR(signintime) < 11 THEN 1 ELSE 0 END) '10AM-11AM',
SUM(CASE WHEN HOUR(signintime) > 11 AND HOUR(signintime) < 12 THEN 1 ELSE 0 END) '11AM-12PM',
SUM(CASE WHEN HOUR(signintime) > 12 AND HOUR(signintime) < 13 THEN 1 ELSE 0 END) '12PM-1PM',
SUM(CASE WHEN HOUR(signintime) > 13 AND HOUR(signintime) < 14 THEN 1 ELSE 0 END) '1PM-2PM',
SUM(CASE WHEN HOUR(signintime) > 14 AND HOUR(signintime) < 15 THEN 1 ELSE 0 END) '2PM-3PM',
SUM(CASE WHEN HOUR(signintime) > 15 AND HOUR(signintime) < 16 THEN 1 ELSE 0 END) '3PM-4PM',
SUM(CASE WHEN HOUR(signintime) > 16 AND HOUR(signintime) < 17 THEN 1 ELSE 0 END) '4PM-5PM',
SUM(CASE WHEN HOUR(signintime) > 17 AND HOUR(signintime) < 18 THEN 1 ELSE 0 END) '5PM-6PM',
SUM(CASE WHEN HOUR(signintime) > 18 AND HOUR(signintime) < 19 THEN 1 ELSE 0 END) '6PM-7PM',
SUM(CASE WHEN HOUR(signintime) > 19 AND HOUR(signintime) < 20 THEN 1 ELSE 0 END) '7PM-8PM'
FROM session
WHERE session.status = '3'
GROUP by HOUR(signintime), Date;
If you notice the picture above, the total is 1 for that entire day (Apr 19, 2013) now if you notice the times (8AM - 8PM) they are all zeroed out. I am unsure as to where to turn to / where to debug this. Hopefully with another set of eyes I can get this moving along.
Regards.
You should not need to use both the > and < to get the result, you can just check the hour value:
select DATE_FORMAT(signintime, '%b %d, %Y') Date,
count(session_id) as Total,
SUM(CASE WHEN HOUR(signintime) = 08 THEN 1 ELSE 0 END) '8AM-9AM',
SUM(CASE WHEN HOUR(signintime) = 09 THEN 1 ELSE 0 END) '9AM-10AM',
SUM(CASE WHEN HOUR(signintime) = 10 THEN 1 ELSE 0 END) '10AM-11AM',
SUM(CASE WHEN HOUR(signintime) = 11 THEN 1 ELSE 0 END) '11AM-12PM',
SUM(CASE WHEN HOUR(signintime) = 12 THEN 1 ELSE 0 END) '12PM-1PM',
SUM(CASE WHEN HOUR(signintime) = 13 THEN 1 ELSE 0 END) '1PM-2PM',
SUM(CASE WHEN HOUR(signintime) = 14 THEN 1 ELSE 0 END) '2PM-3PM',
SUM(CASE WHEN HOUR(signintime) = 15 THEN 1 ELSE 0 END) '3PM-4PM',
SUM(CASE WHEN HOUR(signintime) = 16 THEN 1 ELSE 0 END) '4PM-5PM',
SUM(CASE WHEN HOUR(signintime) = 17 THEN 1 ELSE 0 END) '5PM-6PM',
SUM(CASE WHEN HOUR(signintime) = 18 THEN 1 ELSE 0 END) '6PM-7PM',
SUM(CASE WHEN HOUR(signintime) = 19 THEN 1 ELSE 0 END) '7PM-8PM'
from session
WHERE session.status = '3'
group by DATE_FORMAT(signintime, '%b %d, %Y');
See SQL Fiddle with Demo