mysql getting average of client per day in a month - mysql

SELECT COUNT(client_ID) / DAY(LAST_DAY(dateRequested))
FROM `tbl_client`
WHERE dateRequested BETWEEN DATE_FORMAT(dateRequested,'%Y-%m-01') AND LAST_DAY(dateRequested)
I want to show the average of client per day in the month
client_ID | dateRequested
1 | 2018-07-04
2 | 2018-07-05
3 | 2018-07-06
4 | 2018-07-07
5 | 2018-08-04
6 | 2018-08-06
7 | 2018-08-09
i want to show
Average | Month
4 | July 2018
3 | August 2018

Try below query:
SELECT COUNT(client_ID),concat(month(dateRequested),year(dateRequested))
FROM `tbl_client`
WHERE dateRequested BETWEEN DATE_FORMAT(dateRequested,'%Y-%m-01') AND LAST_DAY(dateRequested)
group by concat(month(dateRequested),year(dateRequested))

Related

How to write an SQL query to calculate the average for three consecutive values?

I have a table like this
userID time NoOfVisits
1 2014 50
2 2015 60
3 2016 70
4 2017 80
5 2018 90
6 2019 100
I need to write a sql query which will print time and average of past 3 years NoOfVisits for a particular site.
output should be as
userID time NoOfVisits
1 2014 50.0000
2 2015 55.0000
3 2016 60.0000
4 2017 70.0000
5 2018 80.0000
6 2019 90.0000
Explanation :
For user Id 6 (80+90+100)/3=90.0000
Please help me to solve this problem.
You can use a cumulative average, available in MySQL 8+:
select t.*,
avg(visits) over (order by time rows between 2 preceding and current row) as avg_visits_3
from t;
Assuming there are no gaps between the years (like your sample data), you can self join the table and group by userid, time to get the average:
select
t.userid, t.time, avg(tt.noofvisits) NoOfVisits
from tablename t inner join tablename tt
on tt.time between t.time - 2 and t.time
group by t.userid, t.time
See the demo.
Results:
| userid | time | NoOfVisits |
| ------ | ---- | ---------- |
| 1 | 2014 | 50 |
| 2 | 2015 | 55 |
| 3 | 2016 | 60 |
| 4 | 2017 | 70 |
| 5 | 2018 | 80 |
| 6 | 2019 | 90 |

Group by date every 10 days

I have this scheme:
+----+--+--------+--------------------+
| ID | Amount | paydate |
+----+-----------+--------------------+
| 1 | 200 |2016-11-05 |
+----+-----------+--------------------+
| 2 | 3000 |2016-11-10 |
+----+-----------+--------------------+
| 3 | 2500 |2016-11-11 |
+----+-----------+--------------------+
| ID | 100 |2016-11-21 |
+----+-----------+--------------------+
| 1 | 200 |2016-11-22 |
+----+-----------+--------------------+
| 2 | 3000 |2016-11-23 |
+----+-----------+--------------------+
| 3 | 2500 |2016-11-29 |
+----+-----------+--------------------+
How can I get the total Amount grouped by every 10 days like from the first of every month to the 10th then from 11th to 20th and from 21st to the end of the month?
to be shown like this :
+-----------+------------------------+
| Amount | paydate |
+-----------+------------------------+
| 3200 |2016-11-1 to 2016-11-10 |
+-----------+------------------------+
| 2500 |2016-11-11 to 2016-11-20|
+-----------+------------------------+
| 5800 |2016-11-21 to 2016-11-31|
+-----------+------------------------+
I tried
SELECT
SUM(Amount) AS Amount,
year(Facture.paydate) AS Annee,
month(Facture.paydate) AS Mois
FROM Facture
GROUP BY year(Facture.paydate), month(serFacture.paydate)
but this does not give me the result I need.
select sum(Amount) as sum_amount
,case
when day(paydate) <= 10 then concat(DATE_FORMAT(paydate,'%Y-%m-01'),' to ',DATE_FORMAT(paydate,'%Y-%m-10'))
when day(paydate) <= 20 then concat(DATE_FORMAT(paydate,'%Y-%m-11'),' to ',DATE_FORMAT(paydate,'%Y-%m-20'))
else concat(DATE_FORMAT(paydate,'%Y-%m-21'),' to ',DATE_FORMAT(paydate,'%Y-%m-31'))
end as paydate_period
from t
group by paydate_period
;
sum_amount paydate_period
3200 2016-11-01 to 2016-11-10
2500 2016-11-11 to 2016-11-20
5800 2016-11-21 to 2016-11-31
Here is an example query:
select
case
when day(date_field) between 1 and 10 then "01 to 10"
when day(date_field) between 11 and 20 then "11 to 20"
when day(date_field) between 21 and 31 then "21 to 31"
end as the_range,
date_format(date_field, "%m%Y") as the_month,
count(*)
from
the_table
group by
the_range, the_month
order by
the_month, the_range;
You can adapt the query so you display your result the way you need.

MySQL `SUM` with `GROUP BY` is missing data in results

I have a database with a table containing information on some images, each row containing a createdAt date and a viewCount. The data ranges from September 2014 until today (July 2016). I want to get a monthly sum of the amount of views across all images for the month
When I run the query
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images
GROUP BY MONTH(createdAt);
I'm only returned 12 rows with results between September 2014 and August 2015
Year | Month | Views
-------------------
2014 | 9 | 1452
2014 | 10 | 279
2014 | 11 | 34428
2014 | 12 | 4763
2015 | 1 | 2826
2015 | 2 | 777
2015 | 3 | 568
2015 | 4 | 1309
2015 | 5 | 46744
2015 | 6 | 1541
2015 | 7 | 8160
2015 | 8 | 91
If I add a date restraint it will give me the latest data, but again only 12 rows
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images WHERE createdAt > DATE('2015-08-01 00:00:00')
GROUP BY MONTH(createdAt);
Year | Month | Views
--------------------
2015 | 8 | 981
2015 | 9 | 1031
2015 | 10 | 2566
2015 | 11 | 3325
2015 | 12 | 411
2016 | 1 | 2140
2016 | 2 | 710
2016 | 3 | 714
2016 | 4 | 1985
2016 | 5 | 426
2016 | 6 | 119
2016 | 7 | 81
I do realise that since it's July the second query stops there as that's where the data ends, but why does the first query not return all the results?
Group by year/month:
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images
--WHERE createdAt > DATE('2015-08-01 00:00:00')
GROUP BY YEAR(createdAt), MONTH(createdAt);
Related Group by clause in mySQL and postgreSQL, why the error in postgreSQL?
Keep in mind that from MySQL 5.7.6+ your initial query may not even work because of only_full_group_by which is set by default.
You can simply add Year to you group by
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images
GROUP BY YEAR(createdAt), MONTH(createdAt)
ORDER BY YEAR(createdAt), MONTH(createdAt)

Mysql - Rows within hourly ranges on specific days using DAYOFWEEK

I am trying to get a query that will return a result set with reading total within certain hour ranges (defined in the working_hours table) depending on the DAYOFTHEWEEK for the date with a result that looks like:
working | nonworking | weekend | date | group_id
-----------------------------------------------------------------
50.3 | 30.8 | 0 | 2015-04-01 00:00 | 7
40.3 | 60.8 | 0 | 2015-04-01 00:00 | 8
50.3 | 30.8 | 0 | 2015-04-02 00:00 | 7
40.3 | 60.8 | 0 | 2015-04-02 00:00 | 8
Working and Weekend ranges are stored in the database in working_hours, Nonworking time ranges are implied (NOT BETWEEN the other ranges on that day basically)
The tables are as following:
Readings table has the hourly readings, named readings
group_id | reading | datestamp
------------------------------------------------------
7 | 30.8 | 2015-04-01 00:00
7 | 20.2 | 2015-04-01 01:00
7 | 11.2 | 2015-04-02 00:00
7 | 20.2 | 2015-04-02 01:00
8 | 26.2 | 2015-04-01 00:00
8 | 30.2 | 2015-04-01 01:00
8 | 26.2 | 2015-04-02 00:00
8 | 30.2 | 2015-04-02 01:00
Hour Ranges are stored in the working_hours table, the day column is DAYOFTHEWEEK format (1 = Sunday, 2 = Monday, etc):
group_id | day | range_start | range_end | range_type_id | day_type_id
------------------------------------------------------------------------------
7 | 5 | 08:00:00 | 15:59:00 | 1 | 1
7 | 6 | 00:00:00 | 05:59:00 | 1 | 2
7 | 6 | 06:00:00 | 23:59:00 | 2 | 2
7 | 1 | 00:00:00 | 22:59:00 | 2 | 4
7 | 1 | 23:00:00 | 23:59:00 | 1 | 4
Day Types are in the working_hours_day_type table and where things get complicated for me, Weekday and Weekend only have one range but Start/End Weekend have two ranges ('Start Weekend' first range is working hours, second range weekend hours and 'End Weekend' first range is weekend hours, second range working hours).
id | type
------------------
1 | Weekday
2 | Start Weekend
3 | Weekend
4 | End Weekend
Range Types are in the working_hours_range_type table:
id | type
------------------
1 | Working
2 | Weekend
My Mysql knowledge is limited to simple SELECT, INSERT etc and the basics of JOINs - I have found out about HOUR(datestamp) BETWEEN 8 AND 14 but dont know how to get subqueries to iterate within a parent query using WHERE datestamp BETWEEN '2015-04-01 00:00:00' AND '2015-04-02 23:59:00' if in fact thats how its done...
I am not totally clear on what constitutes working hours or non-working hours, but does this work?
SELECT
sum(CASE WHEN rtype.range_type_id = 1 THEN reading ELSE 0 END) AS working
sum(CASE WHEN rtype.range_type_id = 2 THEN reading ELSE 0 END) AS nonworking
CASE WHEN r1.daynum in (7,1) THEN 1 ELSE 0 END as weekend
date(datestamp) as date
r1.group_id
FROM
(SELECT
group_id,
reading,
time(datestamp) as rTime,
case when weekday(datestamp) = 0 THEN 2 #weekday() monday to working hours monday
when weekday(datestamp) = 1 THEN 3
when weekday(datestamp) = 2 THEN 4
when weekday(datestamp) = 3 THEN 5
when weekday(datestamp) = 4 THEN 6
when weekday(datestamp) = 5 THEN 7
when weekday(datestamp) = 6 THEN 1
else NULL
END CASE AS daynum
FROM readings) AS r1
LEFT JOIN working_hours w1
ON (r1.daynum = w1.day)
AND (r1.group_id = w1.group_id)
AND (r1.rTime BETWEEN w1.range_start AND w1.range_end)
LEFT JOIN working_hours_day_type dtype
ON w1.day_type_id = dtype.id
LEFT JOIN working_hours_range_type rtype
ON w1.range_type_id = rtype.id
GROUP BY
CASE WHEN daynum in (7,1) THEN 1 ELSE 0 END,
date(datestamp) as date,
r1.group_id

mysql complex query for monthly report

employee makes entry in the following table when starting new task
from home or office
[tablename=CHECK]
c_id c_sdate c_emp c_task
-------------------------------------------------
1 2013-05-01 01:01:00 1 26 //date 01 from home-----
2 2013-05-01 08:11:00 1 27 //date 01 from office--- Present
3 2013-05-02 03:41:00 1 28 //date 02 from home---
4 2013-05-02 09:12:00 1 29 //date 02 from office-
5 2013-05-02 22:32:00 1 30 //date 02 from home---Present
6 2013-05-03 01:43:00 1 31 //date 03 from home
7 2013-06-03 23:25:00 1 32 //date 03 from home----------Homework
8 2013-06-03 02:15:00 2 33 //other employee
an employe will be considered as present if there 1 or many records where time between 8am and 8pm
an employe will be considered as workedFromHome if there 1 or many records where time NOT between 8am and 8pm, and not present on that day
note: do not count a day as workedFromHome if there is any record time between 8am and 8pm (means workedFromHome is only counted if he is not resent on that day)
I want to display monthly report of a employee eg. c_emp=1 for month eg. 5
like this in 1 query
c_emp presentCount HW_Count
1 3 1
or separatly query 1
c_emp presentCount
1 3
and query 2
c_emp HW_Count
1 1
I have tried for counting present working fine
select count(distinct(date_format(c_sdate,'%e'))) as count
from ita_check
where date_format(c_sdate,'%m')=5
and c_emp=1
and date_format(c_sdate,'%H%i')>=800
and date_format(c_sdate,'%H%i')<=2000
and for counting fromHome giving wrong count
select count(distinct(date_format(c_sdate,'%e'))) as count
from ita_check
where date_format(c_sdate,'%m')=5
and c_eid=1
and c_id not in (
select c_id
from ita_check
where date_format(c_sdate,'%m')=5
and c_eid=1
and (date_format(c_sdate,'%H%i')<=800 or date_format(c_sdate,'%H%i')>=2000)
)
and date_format(c_sdate,'%H%i')<800
or date_format(c_sdate,'%H%i')>2000
in above query for counting Working
the sub query returns 1 and 2
while the outer eliminate c_id=2 but not c_id=1
Try this query
SELECT c_emp,
sum(if(cnt>=1,1,0)) as Office,
count(*)-sum(if(cnt>=1,1,0)) as WFH from (
select c_emp, Date(c_sdate),
sum(if(c_sdate BETWEEN Date(c_sdate) + interval 8 hour
AND Date(c_sdate) + interval 20 hour, 1, 0)) as cnt
from table1
group by c_emp, Date(c_sdate)) tmp
group by c_emp
SQL FIDDLE:
| C_EMP | OFFICE | WFH |
------------------------
| 1 | 2 | 2 |
| 2 | 0 | 1 |
For monthly report
SELECT c_emp, date_format(c_date, '%c %Y') as Mnth,
sum(if(cnt>=1,1,0)) as Office,
count(*)-sum(if(cnt>=1,1,0)) as WFH from (
select c_emp, Date(c_sdate) as c_date,
sum(if(c_sdate BETWEEN Date(c_sdate) + interval 8 hour
AND Date(c_sdate) + interval 20 hour, 1, 0)) as cnt
from table1
group by c_emp, Date(c_sdate)) tmp
group by c_emp,Mnth
SQL FIDDLE:
| C_EMP | MNTH | OFFICE | WFH |
---------------------------------
| 1 | 5 2013 | 2 | 1 |
| 1 | 6 2013 | 0 | 1 |
| 2 | 6 2013 | 0 | 1 |