Checking conditions (date, time) with MySQL - mysql

I need to check if the current time is within a certain range of fields within the DB.
For example in the DB I would store a start time, end time, start date, and end date.
I then need to check if the current date is within the rage of values returned by the query.
I have attempted:
WHERE start_date <= $currdate
AND end_date >= $currdate
AND start_time <= $currtime
AND end_time >= $currtime
Which works great, until we get a situation where the dates overlap two days, in which case the query returns NULL as end_time is obviously LESS than the current time.
I guess I need a way to combine start_date and start_time with end_date and end_time?

Have you tried timestamp()?
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestamp
Perhaps can do something like
WHERE timestamp(start_date, start_time) <= timestamp(currdate, currtime)
AND timestamp(end_date, end_time) >= timestamp(currdate, currtime)
This is assuming, of course, that your start/end date and time are related. Not fully sure what the business logic is behind separating those two fields...

Related

Given a range of dates, how to capture rows that has at least one of those dates in another range of dates? [duplicate]

I have a table of events with a recorded start and end time as a MySQL DATETIME object (in the format YYYY-MM-DD HH:MM:SS. I want to find all events that occur in a specific date range. However, events can span multiple days (and go outside of my date range, but I want to return them if they even overlap by 1 second or more with my date range).
Suggestions?
This will find every event that is completely contained inside the range:
SELECT * FROM table WHERE start_date BETWEEN start_of_range AND end_of_range
AND stop_date BETWEEN start_of_range AND end_of_range
This will find any events where any part of the event overlaps any part of the range:
SELECT * FROM table WHERE start_date <= end_of_range
AND stop_date >= start_of_range
The answers by #Bill the Lizard and #Robert Gamble are correct for the question as asked, but I do wonder if you're asking what you think you are... If you're looking for overlapping events then you need to take into account events longer than your search range.
Monday Tuesday Wednesday Thursday
Search: |-----------|
Shopping |-----| Found OK
Eating |--------| Found OK
Stack Overflow |---------------------------------| Not found!
If you wanted to include SO, you'd do:
SELECT * FROM table WHERE (start_date < end_of_range AND end_date > start_of_range)
SELECT *
FROM table
WHERE startdate >= 'starting date' AND startdate < 'ending date'
OR enddate >= 'starting date' AND enddate < 'ending date'
should work for you.
Make sure you specify 'starting date' and 'ending date' with the time included.
'2008-01-01 00:00:00'' AND '2008-01-31 23:59:59'
This will help to avoid errors where dates are the same, but your time falls within the interval by a few hours, minutes, or seconds.
Basically, you can use regular comparisons -- the ones above should work -- the trick is to check all the different cases that can occur.
A) events with an ending date within the range
B) events with a starting date within the range
C) events with both starting and ending dates within the range
D) events with both starting and ending dates outside the range, but overlapping it
Robert's answer is a good one, but it doesn't take into account case D, where the event starts before the range and ends after the range.
Llya, Roberts answer with,
SELECT * FROM table WHERE start_date <= end_of_range
AND stop_date >= start_of_range
works fine with,
D) events with both starting and ending dates outside the range, but overlapping it
??

SQL SELECT logic

I've been having a bit of trouble thinking this problem through. I can't seem to define a SELECT query which is accurate enough to give me the result I want.
I am storing shift patterns in a table. These shift patterns don't have any restrictions on when they can start and finish (except that they cannot overlap each other per machine)
This is the structure of the table (5 rows of example data)
The only information I have to select with is:
The current time (e.g. 01:45)
The current weekday (e.g. Tuesday)
The issue is when a shift overlaps 00:00. So my question is this:
How would I select the current shift based on the current time and weekday?
Here is an SQL Fiddle of the scenario
Thanks!
You can do this with simple logic. If StartTime < EndTime, then you want to test for times between the two values. If Startime > EndTime, then you want to test for times not between the two values. So this solves the time problem:
SELECT *
FROM webreportshiftsetup
WHERE (StartTime < EndTime and time(now()) between StartTime and EndTime or
StartTime > EndTime and time(now()) not between StartTime and EndTime
) and
dayname(now()) in (StartWeekDay, EndWeekDay)
You have a similar problem with the weekdays. But your question is specifically about times and not weekdays. (That should perhaps be another question.)
If your shifts are one-day (i.e. you need to select only current day) you can do something like
SELECT * FROM shifts
WHERE startWeekDay = DATE_FORMAT(CURDATE(),'%W') AND NOW() BETWEEN startTime AND endTime
Otherwise, if your shift starts on Monday and finishes on Wednesday, and today is Tuesday, you will have trouble finding todays shift with a query. For that you should store days as number: 1- Monday, 2- Friday, ...
I would suggest that you change the schema. One option is to use the datetime type for start/end, instead of using varchar for everything.
Then you can query it like:
SELECT *
FROM webreportshiftsetup
WHERE NOW() BETWEEN StartDateTime AND EndDateTime
and so forth.
If you need this to be a repeating thing to where specific dates won't work, then you might make the StartDay/EndDay columns tinyint and give them a value of 1-7, with the smallest number being the first day of the week and the largest number representing the last day of the week. StartTime/EndTime would be date type. Querying that would look like:
SELECT *
FROM webreportshiftsetup
WHERE StartDay >=2 AND EndDay <=4 AND StartTime >= '2:00' AND EndTime <= '13:00'

How best to store time ranges like Tuesday 10-11am?

It's not a one-of, not only one particular Tuesday, so I won't use time stamps.
I mean something like "every Tuesday from 10am to 11am". What's the best way to store this to make it easy to check from my (Delphi) application if the current time is between those permitted times?
Sounds like the time range would simply be an attribute of whichever primary object you are working with, as such you could add a separate table to store the time range data, something like:
object_time_range
id
object_id
day
hour_start
hour_end
frequency_id
-- Update --
In hindsight I would probably abstract hour from the column names in favor of time, just in case you need to consider alternative time frames. And day should be day_id, even though its a static list, I always like going with ints in this situation.
object_time_range
id
object_id
day_id
time_start
time_end
frequency_id
Store the variable as datetime or timestamp,
you can use mysql date functions such as
date_format and date_add
to get the rows which fall within required dates and time
if you store it as text it would be very difficult.
E.g To get rows for the past one day
select * from tableName
where dateField > date_add(now(),interval -1 day) and
dateField < now()
rows for the past one Week
select * from tableName
where dateField > date_add(now(),interval -1 week) and
dateField < now()
Check date_add funciton

Comparing Dates in yyyy-mm-dd format

There's a query I'm working on that has
... WHERE start_date >= DATE(NOW()) AND end_date >= DATE(NOW())
start_date/end_date are in the date format: yyyy-mm-dd
What kinds of results should be expected from this kind of query?
Both start_date and end_date is greater than or equal to today's date.
Instead of using DATE(now()) you can use CURRENT_DATE().
What kinds of results should be expected from this kind of query?
If start_date and end_date are proper mySQL DATE fields, it should work just fine and return all entries where start_date AND end_date are today's date, or a date in the future.
If they are varchar fields, you may want to consider converting the columns into DATE fields - I assume the values are going to remain but make a backup of course - or casting them as DATE fields (slow!):
WHERE CONVERT(start_date, DATE) => DATE(NOW()) AND CONVERT(end_date, DATE) => DATE(NOW())
you will be comparing dates at the date (i.e. time not considered) level of granularity. i.e. all rows where the day is on or later than today (NOW()), assuming that start_date and end_date are date columns.
This should work fine, as you can use NOW() within a date comparision.
However, you don't need to wrap NOW() within DATE - it'll work as-is as long as you're using one of the time related (DATE, DATETIME, TIMESTAMP, etc.) field types.
As such, you should just be able to use...
WHERE start_date >= NOW() AND end_date >= NOW()
That would work, provided that you surrounded start_date and end_date with single quotes. It would give you all the records where the start date and end date are in the future.

Are there any MySQL functions to get all rows with with a start or end date that fall between a given start and end date?

I have a table of events with a recorded start and end time as a MySQL DATETIME object (in the format YYYY-MM-DD HH:MM:SS. I want to find all events that occur in a specific date range. However, events can span multiple days (and go outside of my date range, but I want to return them if they even overlap by 1 second or more with my date range).
Suggestions?
This will find every event that is completely contained inside the range:
SELECT * FROM table WHERE start_date BETWEEN start_of_range AND end_of_range
AND stop_date BETWEEN start_of_range AND end_of_range
This will find any events where any part of the event overlaps any part of the range:
SELECT * FROM table WHERE start_date <= end_of_range
AND stop_date >= start_of_range
The answers by #Bill the Lizard and #Robert Gamble are correct for the question as asked, but I do wonder if you're asking what you think you are... If you're looking for overlapping events then you need to take into account events longer than your search range.
Monday Tuesday Wednesday Thursday
Search: |-----------|
Shopping |-----| Found OK
Eating |--------| Found OK
Stack Overflow |---------------------------------| Not found!
If you wanted to include SO, you'd do:
SELECT * FROM table WHERE (start_date < end_of_range AND end_date > start_of_range)
SELECT *
FROM table
WHERE startdate >= 'starting date' AND startdate < 'ending date'
OR enddate >= 'starting date' AND enddate < 'ending date'
should work for you.
Make sure you specify 'starting date' and 'ending date' with the time included.
'2008-01-01 00:00:00'' AND '2008-01-31 23:59:59'
This will help to avoid errors where dates are the same, but your time falls within the interval by a few hours, minutes, or seconds.
Basically, you can use regular comparisons -- the ones above should work -- the trick is to check all the different cases that can occur.
A) events with an ending date within the range
B) events with a starting date within the range
C) events with both starting and ending dates within the range
D) events with both starting and ending dates outside the range, but overlapping it
Robert's answer is a good one, but it doesn't take into account case D, where the event starts before the range and ends after the range.
Llya, Roberts answer with,
SELECT * FROM table WHERE start_date <= end_of_range
AND stop_date >= start_of_range
works fine with,
D) events with both starting and ending dates outside the range, but overlapping it
??