MySQL data in 15 Minutes Increments - mysql

I am trying to create high charts time line graph for my school attendance but I get slightly different records appearing in my result.
The table that stores attendance is :
+++++++++++++++++++++++++++++++++
Id | Date | AttendTime(varchar)
--------------------------------
1 | 20160815 | 7:51
2 | 20160815 | 7:53
3 | 20160815 | 8:01
-------------------------------
I am using following sql to get the data
SELECT
COUNT(Id) as Total
FROM Attendance
WHERE Date = '20160815' AND
HOUR(STR_TO_DATE(AttendTime, '%H:%i')) <= HOUR(STR_TO_DATE('7:30', '%H:%i'))
And I should get 0 as there are none but I get 3 records. What am I doing wrong?
Thank you.

If you are simply trying to see how many attendances were before 7:30, you do not need the HOUR function:
SELECT
COUNT(Id) as Total
FROM Attendance
WHERE Date = '20160815'
AND STR_TO_DATE(AttendTime, '%H:%i') <= STR_TO_DATE('7:30', '%H:%i')

Related

mysql to check Instructor is available for lesson at selected time

I have a lesson booking calendar and I am trying to check if the Instructor is booked at given time or is available.
I have following table for saving lesson_registrations
| id | InstructorId | startTime | endTime |
| 1 | 2 | 201806271100 | 201806271200 |
| 2 | 2 | 201806271400 | 201806271500 |
So according to this table Instructor is available for a lesson between 201806271200 to 201806271400 but when I run the following query it marks the Instructor to be booked.
SELECT * FROM lesson_registrations
WHERE
((startTime BETWEEN '201806271200' AND '201806271400' )
OR (endTime BETWEEN '201806271200' AND '201806271400')
OR ('201806271200' BETWEEN startTime AND endTime)
OR ('201806271400' BETWEEN startTime AND endTime) )
What am I doing wrong here?
Thank you
The correct logic for finding any overlaps would be:
select lr.*
from lesson_registrations lr
where lr.startTime < 201806271400 and
lr.endTime > 201806271200;
To get instructors who are avaialable:
select i.*
from instructors i
where not exists (select 1
from lesson_registrations lr
where lr.instructorId = i.instructorId and
lr.startTime < 201806271400 and
lr.endTime > 201806271200
);
The logic basically says that an instructor is not available if the following two conditions are true:
The a lesson starts any time before the end time.
The same lesson ends any time after the start time.
I think that because between is inclusive the statement is catching the records with 201806271200 as endtime.
If you run the following you get no results showing that there are lessons available.
SELECT * FROM lesson_registrations
WHERE
(startTime BETWEEN '201806271159' AND '201806271359' )
yea 1200 counts as the end time so the start time of the next needs to be in 1201 or the endtime needs to be in 1159 and the start time can be 1200

SQL get the time when user access the most

We have a list of page url and dateTime record on database.
Is it possible to get the hour where user have access it the most?
The column time displays what time users have access the url the most.
The expected result should look like these:
page URL | # visitor per day | Date | Max visitor/hour| time
----------+-------------------+--------------------+-----------------+--------------
www.url1 | 49 | 07/07/2017 | 23 | 12:00 - 13:00
www.url2 | 88 | 07/07/2017 | 39 | 7:00 - 8:00
In Subquery get the max hour per each URL and day.
Then join that to the main table, to get the required records.
If you need max hour irrespective of day, then just drop Date column from sub query and the join condition.
select *
from maintable
join
( select pageURL, Date, max(MaxVisitorPerHour) as maxhour
from table
group by pageURL, Date) subq
on
(maintable.pageURL=subq.pageURL AND maintable.Date=subq.Date and
maintable.maxVisitorPerHour=subq.maxhour)

Date Difference from Log table

Hello guys I need help with this function, I'm using MySQL database server
version: 5.5.47-0ubuntu0.14.04.1 - (Ubuntu).
I want to be able to get how many "weeks" it took a worker to get hired. i have a table that stores log data whenever the worker's status change.
logid workerid statusid timestamp
1000 10 1(available) 2016-04-10
1001 10 2(Hired) 2016-04-24
what i want to have is :
It took worker 10 two weeks to get hired.
I already looked at DATEDIFF(first date, second date) function but I have to use two different where conditions for each date, I have no idea how to do this?
You need to join same table and to use DATEDIFF():
SELECT
e1.workerid,
DATEDIFF(e2.`timestamp`, e1.`timestamp`) daysDiff,
ROUND(DATEDIFF(e2.`timestamp`, e1.`timestamp`) / 7, 0) weeksDiff
FROM
employees e1
INNER JOIN employees e2 ON e1.workerid = e2.workerid
WHERE
e1.statusid = 1
AND e2.statusid = 2
Output:
+----------+----------+-----------+
| workerid | daysDiff | weeksDiff |
+----------+----------+-----------+
| 10 | 14 | 2 |
+----------+----------+-----------+
1 row in set

Graph per-day from ranges in MySQL

I am trying to make a graph that has a point for each day showing the number of horses present per-day.
This is example of data I have (MySQL)
horse_id | start_date | end_date |
1 | 2011-04-02 | 2011-04-03 |
2 | 2011-04-02 | NULL |
3 | 2011-04-04 | 2014-07-20 |
4 | 2012-05-11 | NULL
So a graph on that data should output one row per day starting on 2011-04-02 and ending on CURDATE, for each day it should return how many horses are registered.
I can't quite wrap my head around how I would do this, since I only have a start date and an end date for each item, and I want to know per-day how many was present on that day.
Right now, I do a loop and a SQL query per day, but that is - as you might have guesses - thousands of queries, and I was hoping it could be done smarter.
If a day between 2011-04-02 and now contains nothing, I still want it out but with a 0.
If possible I would like to avoid having a table with a row for each day containing a count.
I hope it makes sense, I am very stuck here.
What you should have, is a table containing just dates from at least the earliest date in your current table till the current date.
Then you can use this table to left join it something like this:
SELECT
dt.date,
COUNT(yt.horse_id)
FROM
dates_table dt
LEFT JOIN your_table yt ON dt.date BETWEEN yt.start_date AND COALESCE(end_date, CURDATE())
GROUP BY dt.date
Be sure to have a column of your_table in the COUNT() function, otherwise it counts the NULL values too.
The COALESCE() function returns the first of its parameter which isn't NULL, so if you don't have an end_date specified, the current date is taken instead.

Get total number of records on that day in a table in an array in last 30 days

I want to plot a graph to see the user growth in last 30 days.
So it will an array something like this: (an incremental array)
[0,100,250,500,1000,1100.....5000,5500]
Solution 1: A stupid way to do this is to fire query for every day:
(30.days.ago.to_date..Date.today).map {|date| User.where("Date(created_at) <= ?" , date).count}
But this will fire 30 queries.
Solution 2: Find all records using group by option and then loop over it and sumup previous records.
User.group('Date(created_at)').count
(30.days.ago.to_date..Date.today).map {|date| counts[date] || 0} //and again loop over it
//and now start summing up previous ones elements to get an another array..
But both the solutions are useless. Any suggestions to make this as optimised ones.
I'll do the following :
growth = []
users = User.group('Date(created_at)').count
(30.days.ago.to_date..Date.today).each do |day|
growth.push(growth.sum + (users[day] || 0))
end
Not tested but you get the idea.
You should be able to do this with sql itself,
Ex: I have the following table
+---------+---------------------+
| user_id | training_start_date |
+---------+---------------------+
| 15981 | 2012-10-08 06:12:45 |
| 15981 | 2012-10-08 06:13:26 |
| 15981 | 2012-10-08 06:29:34 |
| 15981 | 2012-10-08 06:33:53 |
| 1005933 | 2012-10-08 07:41:54 |
+---------+---------------------+
when I want to get how many users got the training each day, I could do
select count(user_id), training_start_date from training_users group by DATE_FORMAT(training_start_date, "%M %e, %Y");
This is the link which helped me
HTH