Mysql Get data for Last Six weeks using JOIN - mysql

I have edited the query by selecting all the Employees data which have done assessments in past six weeks. Logically it should each employee two time if it has done assessments in two weeks but this query shows single record.
select
AssessmentEmployee.
EmployeeName,
AVG(AssessmentListing.AssessmentScore),
DATE_FORMAT((STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p')) , '%Y-%m-%v') as _month
from AssessmentEmployee
LEFT JOIN AssessmentListing
ON AssessmentEmployee.AssessmentID=AssessmentListing.AssessmentID
WHERE (STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >= DATE_FORMAT(NOW() - INTERVAL 6 Week, '%Y' ))
group by AssessmentEmployee.EmployeeName
I have following table which I am using.
AssessmentEmployee
ID
AssessmentID
EmployeeName
Other table is AssessmentListing
ID
AssessmentID
AssessmentSubmittedDateTime
AssessmentScore
I want to get the employees who have score/ done assessments in Last sex weeks and their average score.
Sample of Data Column of AssessmentListing
ID AssessmentID AssessmentSubmittedDatetime AssessmentScore
1 040416024720 04-Apr-2016 02:48 PM 50

Please try the following query:
select
AssessmentEmployee.
EmployeeName,
AVG(AssessmentListing.AssessmentScore),
DATE_FORMAT((STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p')) , '%Y-%v') as year_week
from AssessmentEmployee
LEFT JOIN AssessmentListing
ON AssessmentEmployee.AssessmentID=AssessmentListing.AssessmentID
WHERE UNIX_TIMESTAMP(DATE_FORMAT(STR_TO_DATE(`AssessmentSubmittedDatetime`,'%d-%b-%Y %I:%i %p'),'%Y-%m-%d')) >= UNIX_TIMESTAMP(CURDATE() - INTERVAL 6 WEEK)
group by AssessmentEmployee.EmployeeName, year_week;
You shouldn't store date / time as string. Otherwise embrace these cumbersome jobs while processing them.

you're doing an average so it will average the 2 scores if they take it twice.

SELECT *, SUM(AssessmentScore) as total, SUM(AssessmentScore)/6 as avg
FROM `assessmentlisting`
WHERE STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') > DATE_FORMAT(NOW() - INTERVAL 6 Week, '%Y-%m-%d %I:%i %p' )
GROUP BY assessmentlisting.AssessmentID
Hope it will works.

Related

How to count only business days (Monday to Friday) per month between two dates in MySQL 5.7?

I have the following table called vacations, where the employee id is displayed along with the start and end date of their vacations:
employee
start
end
1001
26/10/21
22/11/21
What I am looking for is to visualize the number of vacation days that each employee had, but separating them by month and without non-working days (Saturdays and Sundays).
For example, if you wanted to view the vacations for employee 1001, the following result should be displayed:
days
month
4
10
16
11
I have the following query that I have worked with:
SELECT id_employee,
EXTRACT(YEAR_MONTH FROM t.Date) as YearMonth,
COUNT(1) as Days
FROM (SELECT v.id_employee,
DATE_ADD(v.start, interval s.seq - 1 DAY) AS Date
FROM vacations v
CROSS JOIN seq_1_to_100 s
WHERE DATE_ADD(v.start, interval s.seq - 1 DAY) <= v.end
ORDER BY v.id_employee, , v.start, s.seq
) t
GROUP BY id_employee,
EXTRACT(YEAR_MONTH FROM t.Date)
With this query I separate the days between a range of two dates with their respective month, but how could I adapt it to stop considering Saturdays and Sundays? I'm working with MySQL 5.7 in phpMyAdmin
instead of count sum the compaarison of weekday function, which give what day it is .
But you should always save fates n a valid mysql manner 2021-10-28
SELECT id_employee,
EXTRACT(YEAR_MONTH FROM t.Date) as YearMonth,
SUM(WEEKDAY(`Date`) < 5) as Days
FROM (SELECT v.id_employee,
DATE_ADD(v.start, interval s.seq - 1 DAY) AS Date
FROM vacations v
CROSS JOIN seq_1_to_100 s
WHERE DATE_ADD(v.start, interval s.seq - 1 DAY) <= v.end
ORDER BY v.id_employee, v.start, s.seq
) t
GROUP BY id_employee,
EXTRACT(YEAR_MONTH FROM t.Date)

group by date_format for each day

My I'm having problems with a query.
Here is what I have
SELECT COUNT(id) as Counted
FROM referral_code_logs
GROUP BY DATE_FORMAT(time_stamp, '%c/%e/%y');
I am trying to see the amount of referrals each day has. The part I'm having problems with is the date_format.
Table layout
Here are how the time_stamps are entered in the Table: (month/day/year)
month is 1-12 day is 0-31 year is YY
Time_stamps
You just need to add in the date to the select part:
SELECT DATE_FORMAT(STR_TO_DATE(time_stamp, '%c/%e/%y'), '%c/%e/%y') as DT
,COUNT(id) as Counted
FROM referral_code_logs
GROUP BY DATE_FORMAT(time_stamp, '%c/%e/%y');

How to get data count for last three months as separate in single query?

I want to get count of all assessments in past three months. So this should count for current and previous two months as separate
like Count1 50 for this month
Count2 100 for one month back
Count2 50 for two month back
SELECT Count(AssessmentID)
from AssessmentListing
WHERE (STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >=
DATE_FORMAT(NOW(), '%Y' ))
You should not be storing dates as strings. If you want the current month and two months back, then something like this:
SELECT DATE_FORMAT(STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p'), '%Y-%m') as yyyymm,
Count(*)
from AssessmentListing
WHERE STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >= DATE_SUB(DATE_SUB(CURDATE(), INTERVAL 1 - DAY(CURDATE()), INTERVAL 2 MONTH)
GROUP BY yyyymm;
I am not sure what your WHERE clause actually does. But comparing a string and a date is probably not what you really want.
Like #Jarlh mentioned in comment you can use Extract function to extract the month from the date column and group the result using that.
select EXTRACT(MONTH FROM AssessmentSubmittedDatetime) as _month,
Count(AssessmentID)
from AssessmentListing
WHERE (STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >=
DATE_FORMAT(NOW(), '%Y' ))
group by _month

MySql query histogram for time intervals data

I have an event input of this type
event user
event start
event end
event type
Inserted to MySql table, each in its own row with user+start as primary key.
I need to query an histogram for a type by time interval (say minute) counting events occurred on each time interval.
something like:
SELECT count(*) as hits FROM events
WHERE type="browsing"
GROUP BY time_diff("2015-1-1" AND "2015-1-2") / 60 * second
but I could not find any way to do that in SQL besides writing code, any idea?
Sample data
user, start, end, type
1, 2015-1-1 12:00:00, 2015-1-1 12:03:59, browsing
2, 2015-1-1 12:03:00, 2015-1-1 12:06:00, browsing
2, 2015-1-1 12:03:00, 2015-1-1 12:06:00, eating
3, 2015-1-1 12:03:00, 2015-1-1 12:08:00, browsing
the result should look like this:
^
count |
browsing |
users | *
| * * * *
| * * * * * * * *
--|--|--|--|--|--|--|--|--|--> minute
0 1 2 3 4 5 6 7 8 9
You can do this using group by with the level that you want. Here is an example using the data you gave:
First the SQL to create the table and populate it. The ID column here isn't "needed" but it is recommended if the table will be large or have indexes on it.
CREATE TABLE `test`.`events` (
`id` INT NOT NULL AUTO_INCREMENT,
`user` INT NULL,
`start` DATETIME NULL,
`end` DATETIME NULL,
`type` VARCHAR(45) NULL,
PRIMARY KEY (`id`));
INSERT INTO events (user, start, end, type) VALUES
(1, '2015-1-1 12:00:00', '2015-1-1 12:03:59', 'browsing'),
(2, '2015-1-1 12:03:00', '2015-1-1 12:06:00', 'browsing'),
(2, '2015-1-1 12:03:00', '2015-1-1 12:06:00', 'eating'),
(3, '2015-1-1 12:03:00', '2015-1-1 12:08:00', 'browsing');
To get a list of ordered pairs of number of minutes duration to number of events:
The query can then be easily written using the timestampdiff fuction, as shown below:
SELECT
TIMESTAMPDIFF(MINUTE, start, end) as minutes,
COUNT(*) AS numEvents
FROM
test.events
GROUP BY TIMESTAMPDIFF(MINUTE, start, end)
The output:
minutes numEvents
3 3
5 1
The first parameter in the select can be one of FRAC_SECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or YEAR.
Here are some more examples of queries you can do:
Events by hour (floor function is applied)
SELECT
TIMESTAMPDIFF(HOUR, start, end) as hours,
COUNT(*) AS numEvents
FROM
test.events
GROUP BY TIMESTAMPDIFF(HOUR, start, end)
**Events by hour with better formatting **
SELECT
CONCAT("<", TIMESTAMPDIFF(HOUR, start, end) + 1) as hours,
COUNT(*) AS numEvents
FROM
test.events
GROUP BY TIMESTAMPDIFF(HOUR, start, end)
You can group by a variety of options, but this should definitely get you started. Most plotting packages will allow you to specify arbitrary x y coordinates, so you don't need to worry about the missing values on the x axis.
To get a list of ordered pairs of number of events at a specific time (for logging):
Note that this is left for reference.
Now for the queries. First you have to pick which item you want to use for the grouping. For example, a task might take more than a minute, so the start and end would be in different minutes. For all these examples, I am basing them off of the start time, since that is when the event actually took place.
To group event counts by minute, you can use a query like this:
SELECT
DATE_FORMAT(start, '%M %e, %Y %h:%i %p') as minute,
count(*) AS numEvents
FROM test.events
GROUP BY YEAR(start), MONTH(start), DAYOFMONTH(start), HOUR(start), MINUTE(start);
Note how this groups by all the items, starting with year, going the minute. I also have the minute displayed as a label. The resulting output looks like this:
minute numEvents
January 1, 2015 12:00 PM 1
January 1, 2015 12:03 PM 3
This is data that you could then take using php and prepare it for display by one of the many graphing libraries out there, plotting the minute column on the x axis, and plotting the numEvents on the y axis.
Here are some more examples of queries you can do:
Events by hour
SELECT
DATE_FORMAT(start, '%M %e, %Y %h %p') as hour,
count(*) AS numEvents
FROM test.events
GROUP BY YEAR(start), MONTH(start), DAYOFMONTH(start), HOUR(start);
Events by date
SELECT
DATE_FORMAT(start, '%M %e, %Y') as date,
count(*) AS numEvents
FROM test.events
GROUP BY YEAR(start), MONTH(start), DAYOFMONTH(start);
Events by month
SELECT
DATE_FORMAT(start, '%M %Y') as date,
count(*) AS numEvents
FROM test.events
GROUP BY YEAR(start), MONTH(start);
Events by year
SELECT
DATE_FORMAT(start, '%Y') as date,
count(*) AS numEvents
FROM test.events
GROUP BY YEAR(start);
I should also point out that if you have an index on the start column for this table, these queries will complete quickly, even with hundreds of millions of rows.
Hope this helps! Let me know if you have any other questions about this.
I am going to assume that you have a numbers table that contains integers. You also have $starttime and $endtime.
This is one way to get the values you want:
select ($starttime + interval n.n - 1 minute) as thetime, n.n as minutes,
count(sd.user)
from numbers n left join
sampledata sd
on $starttime + interval n.n - 1 minute between sd.start and sd.end
where $starttime + interval n.n - 1 minute <= $endtime and
sd.end >= $starttime and
sd.start <= $endtime
group by n.n
order by n.n;

Average posts per hour on MySQL?

I have a number of posts saved into a InnoDB table on MySQL. The table has the columns "id", "date", "user", "content". I wanted to make some statistic graphs, so I ended up using the following query to get the amount of posts per hour of yesterday:
SELECT HOUR(FROM_UNIXTIME(`date`)) AS `hour`, COUNT(date) from fb_posts
WHERE DATE(FROM_UNIXTIME(`date`)) = CURDATE() - INTERVAL 1 DAY GROUP BY hour
This outputs the following data:
I can edit this query to get any day I want. But what I want now is the AVERAGE of each hour of every day, so that if on Day 1 at 00 hours I have 20 posts and on Day 2 at 00 hours I have 40, I want the output to be "30". I'd like to be able to pick date periods as well if it's possible.
Thanks in advance!
You can use a sub-query to group the data by day/hour, then take the average by hour across the sub-query.
Here's an example to give you the average count by hour for the past 7 days:
select the_hour,avg(the_count)
from
(
select date(from_unixtime(`date`)) as the_day,
hour(from_unixtime(`date`)) as the_hour,
count(*) as the_count
from fb_posts
where `date` >= unix_timestamp(current_date() - interval 7 day)
and created_on < unix_timestamp(current_date())
group by the_day,the_hour
) s
group by the_hour
Aggregate the information by date and hour, and then take the average by hour:
select hour, avg(numposts)
from (SELECT date(`date`) as day, HOUR(FROM_UNIXTIME(`date`)) AS `hour`,
count(*) as numposts
from fb_posts
WHERE DATE(FROM_UNIXTIME(`date`)) between <date1> and <date2>
GROUP BY date(`date`), hour
) d
group by hour
order by 1
By the way, I prefer including the explicit order by, since most databases do not order the results of a group by. Mysql happens to be one database that does.
SELECT
HOUR(FROM_UNIXTIME(`date`)) AS `hour`
, COUNT(`id`) \ COUNT(DISTINCT TO_DAYS(`date`)) AS avgHourlyPostCount
FROM fb_posts
WHERE `date` > '2012-01-01' -- your optional date criteria
GROUP BY hour
This gives you a count of all the posts, divided by the number of days, by hour.