MySQL: A query to work with timetables? - mysql

In the project I'm working on right now the system stores employees' timetables in the table with the following structure:
employee_id | mon_h_s | mon_m_s | mon_h_e | mon_s_e | tue_h_s | tue_m_s | etc.
------------------------------------------------------------------------------
1 06 00 14 30 06 00 ...
2 18 30 07 00 21 00 ...
where:
mon_h_s - monday hours start
mon_m_s - monday minutes start
mon_h_e - monday hours end
mon_m_e - monday minutes end
tue_... - tuesday...
Every day of the week has 4 fields: hours start, minutes start, hours end, minutes end.
So, from the table above we can see that:
employee with the id 1 works from 06:00 to 14:30 on Monday
employee with the id 2 works from 18:30 to 07:00 on Monday (basically, between Monday and Tuesday, at night)
The problem is that I'm not sure how to create a SQL query which takes into account everything including time overlapping (at night time). For example, we need to find an employee who works at 6am (06:00) on Tuesday. In our case both employees (id 1 and id 2) would satisfy this criteria. Employee with the id 1 starts his work at 06:00 on Tuesday, and employee with the id 2 works until 07:00 Tuesday (starts on Monday though).
Any suggestions on how to solve this problem would be greatly appreciated.

Probably something like:
SELECT (1440 + ((mon_h_e*60)+mon_m_e) - ((mon_h_e*60)+mon_m_e)) % 1440
This will give you the time worked in minutes. Basically, it adds 1440 (minutes in a day, or 24h*60min/h) to the difference between end time and start time, and keep the rest (modulo) of 1440.
Now for the design part:
If you can, redesign your table. Your table need not have all days of the week in one row, that will make tallying of weekly times very tedious.
You should consider using real datetimes.
employee_id | entrytime | exittime
1 | 2011-10-31 06:00:00 | 2011-10-31 14:30:00
1 | 2011-11-01 06:00:00 | null
2 | 2011-10-31 18:30:00 | 2011-11-01 07:00:00
2 | 2011-11-01 21:00:00 | null
That way, you have:
Full access to all date and time functions in MySQL
Easy calculation of duration
Easy filtering on incomplete periods

There are four basic cases that you need o handle
A -> when time of lecture starts before given time
B -> when time of lecture starts after given time but falls within range of ending time
C -> when time of lecture starts within given time but ends after
D -> when time of lecture starts before given time and ends after given time
Now, this can be accomplished using simple OR conditions

Related

MySQL, grouping by and performing a SUM within the groups

The table below contains records of shifts which have taken place. The start and end fields are the start and end timestamps of those shifts. I'm looking to build a query that will extract the total hours per month that the shifts cover.
Example table:
ID Start End
1 2018-10-23 10:30:00 2018-10-23 11:45:00
2 2018-10-22 22:00:00 2018-10-22 23:00:00
3 2018-11-22 22:00:00 2018-11-22 23:00:00
The ideal output would read:
Month Hours
10 2:15
11 1:00
I've got some of the elements worked out, using a SUM(timediff(end,start)) and GROUP BY, but havn't managed to get something good out!
Thanks!
Here you go:
select
month(start) as month,
time_format(sec_to_time(
sum(timestampdiff(second, start, end))
), '%H:%i') as hours,
sum(timestampdiff(second, start, end)) as seconds
from shift
group by month(start)
Result:
month hours seconds
----- ----- -------
10 02:15 8,100
11 01:00 3,600
Note: I added the extra column seconds in case you want to use this numeric value to do some extra processing.

Excel WEEKNUM() vs MySQL YEARWEEK()

I am creating a clock-in time system and so far I have been able to get user clock in time for today and user clock in time for the current week.
The final step is to get user current time for the current pay period.
I have created a list of pay period start & end dates in Excel.
Whenever you use a function like Excel WEEKNUM() or MySQL YEARWEEK(), these functions come with an additional option parameter.
The links below show the differences between these modes in a table.
Excel WEEKNUM() table reference
MySQL YEARWEEK() table reference
My question is, if we do payroll biweekly, which mode do I set in Excel WEEKNUM() that corresponds to MySQL YEARWEEK()?
Attached spreadsheet clock.logic.xlsx
Thank you for any help.
At first the good news: The Excel ISOWEEKNUM function corresponds to the MySQL WEEKOFYEAR which is WEEK(date,3). So determining ISO week numbers is possible.
But all other WEEK modes are simply crap because the definition of the first week in year does not fit any logic used elsewhere. For example, take the simplest mode having Sunday as the first day of the week and the first week of the year is the week, the first day of the year falls in. This is what Excels WEEKNUM function returns with Return_type 1 or omitted. This should be MySQLs WEEK in modus 0 (0-53) or 2 (1-53). But what the heck?
SELECT WEEK('2008-01-01',0); -> 0
SELECT WEEK('2008-01-01',2); -> 52
So MySQL tells us, Tuesday, 2008-01-01, is in week 52 of 2007?
Really? Why?
Because the rule "Week 1 is the first week … with a Sunday in this year" is not fulfilled by MySQL. Instead it seems for MySQL the first week starts with the first Sunday in this year.
So except of the ISO week numbers, all other week numbers from MySQL are wrong. One could think: Let us take modus 0 and simply add 1 to the result. But that fails in 2012. Because there 2012-01-01 is Sunday and there MySQL gives week number 1 in modus 0 as well as in modus 2.
Examples:
Excel:
Date WEEKNUM ISOWEEKNUM
2008-01-01 1 1
2008-02-01 5 5
2008-02-03 6 5
2008-02-04 6 6
2008-12-31 53 1
2009-01-01 1 1
2009-02-01 6 5
2009-12-31 53 53
2012-01-01 1 52
2012-02-01 5 5
2012-12-31 53 1
2016-01-01 1 53
2016-02-01 6 5
2016-12-31 53 52
MySQL:
drop table if exists tmp;
create table tmp (d date);
insert into tmp (d) values
('2008-01-01'),
('2008-02-01'),
('2008-02-03'),
('2008-02-04'),
('2008-12-31'),
('2009-01-01'),
('2009-02-01'),
('2009-12-31'),
('2012-01-01'),
('2012-02-01'),
('2012-12-31'),
('2016-01-01'),
('2016-02-01'),
('2016-12-31');
select d as 'Date', week(d,0), week(d,3) from tmp;
Result:
Date week(d,0) week(d,3)
2008-01-01 0 1
2008-02-01 4 5
2008-02-03 5 5
2008-02-04 5 6
2008-12-31 52 1
2009-01-01 0 1
2009-02-01 5 5
2009-12-31 52 53
2012-01-01 1 52
2012-02-01 5 5
2012-12-31 53 1
2016-01-01 0 53
2016-02-01 5 5
2016-12-31 52 52
If you want to calculate hours in current pay period in Excel, given a two week pay period, then I'd suggest that you don't need week numbers at all (in fact that overcomplicates the calculation, especially at the start or end of the year)
If you have dates in A2:A100 and hours worked on those dates in B2:B100, and a list of pay period start dates in Z2:Z10 then you can get hours in current pay period with this formula
=SUMIF(A2:A100,">="&LOOKUP(TODAY(),Z2:Z10),B2:B100)
I imagine your actual setup is more complicated, but some variation on the above can probably still be used

My sql time range selection

My table
starttime | endtime | id
10:30 11:30 1
11:30 12:30 2
14:30 16:30 3
15:30 16:30 4
I need to find the id in a given time slot for example
say
10:30 to 13:30 should give me o/p 1 2
11:30 to 16:30 should give o/p 2 3 4
The statement I am using
select id from table where STR_TO_DATE(starttime,'%h:%i')>='10:30' and STR_TO_DATE(endtime,'%h:%i')<='22:30';
it gives me only 1 and 2
I am not able to get the correct output what am I doing wrong here?
Note start and end time in varchar
EDIT-
If I wanted to selectthe id's between 10:30 to 12:30 I use this below command
select id from table where STR_TO_DATE(starttime,'%H:%i')>='10:30' and STR_TO_DATE(endtime,'%H:%i')<='12:30';
This gives me only id 1 .. but not giving me 2, If i change 12:30 to 12:40 it gives me 1 & 2.BUt I am using less or equal so it should give me both the id's right? Why its not working like that?
STR_TO_DATE(starttime,'%h:%i')
You are using the format %h which according to the documentation is for:
Hour (01..12)
Essentially, everything above 12 is invalid (Returns NULL).
And, you gave values above 12 to those ids.
Use the specifier
%H
for hours in the format 00 - 23
or the specifier
%k
for hours 0 - 23.

MySQL store time conditions

I am currently working on a platform where I would like to offer some rentals.
I want to store all possible rental types in the database, so I do not need to take care of logic in code.
Basically I want to offer following rental-times:
1 day
7 days
5 days / need to be weekdays ( which is monday to
friday )
2 days / weekend ( needs to be saturday till sunday )
1 month / which will be from e.g. 14 of some month till 13th of following month
For the time of days I thought of storing data in minutes, this is easy to figure out.
If there is a weekday condition I thought of using the DAYOFWEEK Indexes, so I could define for 5 days, the first day of rental needs to have index 2 which is Monday, for weekend I could define that the day of rental needs to have index 6, which is Saturday.
rental_type_id | rental_time_in_minutes | rental_label | rental_start_day_indexes
1 day would be like
1 | 1440 | 1 day | 1,2,3,4,5,6,7
7 days
2 | 10080 | 7 days | 1,2,3,4,5,6,7
5 days
3 | 7200 | Weekdays | 2,3,4,5,6
etc.
Is this a way to go for, or should I store the rental time just in days?
Any help, advice, critics or cheers are helpful!
Thanks.
Depending on how you use this, storing rental time in minutes could cause issues around DST where you have 23 or 25 hours in a day.
Also storing the indices as comma-separated lists will cause you problems. I would make a mapping table. That column is not in normal form and will be tough to query.
I would honestly just make different tables for the different durations.
I would store the durations in seconds. Because it makes the whole thing easier to query and more felxible. Lets say you have those rental durations. Table durations:
d_id type duration
1 1 day 01
2 3 days 03
3 7 days 07
I would suggest that you use normal timestamps for the rentals. I would store the start and end timestamp. Lets say you have the following table.
In this example I'm using days instead of a timestamp just to make it easier to show. Let's say today is day 3. Table rentals:
customer start end
Bob 02 05
Joe 10 11
Ian 03 04
Let's say you want to want to get all the currently active rentals (Bob & Ian). You can fetch it like this:
SELECT * FROM `rentals` WHERE `start`<3 AND 3<`end`
You can find all which of rental type "1 day" (Ian) by using this query:
SELECT * FROM `rentals`,`durations` WHERE `end`-`start`=`duration` and `d_id`=1
The advantage of using timestamps is that you can very precisely set the rental start and end time. You can check how many hours and minutes the customer is too late with giving the object back. Then you can easily calculate the exact additional fees.

MySQL Compare start and finish time

I am trying to create booking system, MySQL table has this row
Room Id | Start (DateTime) | | Finish(DateTime)
13 2014-10-20 08:30 | 2014-10-20 18:30
And I want to block any entries between these start and finish
eg:
Room id: 13
Start: 2014-10-20 10:30
Finish: 2014-10-20 12:30
To do that I have wrote this MySQL query, is this SQL correct?
SELECT *
FROM rooms
WHERE room_id='13'
AND ('2014-10-20 12:30:00' <= start_time OR '2014-10-20 10:30:00'>=finish_time)
In here I tried to skip between result, please advise me.
You want to between the start time and finish time means I didn't test it but once can you try this..I hope it works
SELECT *
FROM rooms
WHERE room_id='13'
AND ('2014-10-20 12:30:00' >= start_time AND '2014-10-20 10:30:00'<=finish_time)