Time difference using MySQL - end time after mid night not working - mysql

I am trying to figure out whether my current time falls between two given times. It is working fine, unless if my end time falls after the mid night, while my start time is during the day.
For example, if I have:
Start: 17:00
End: 03:00
Current: 18:30
It then will not show up.
I do understand where the logic is going wrong, but I can't find a fix for it, logically and conceptually. I mean, you could claim that 06:30 PM does fall between 05 PM and 03 AM, but then 03 AM of the next day!
How do we overcome that problem?
Here is my query below:
SELECT * FROM products
JOIN restaurants
ON (products.Venue = restaurants.name)
WHERE products.Drink_Category = Beer
AND restaurants.Area = Racks
AND (
HOUR(18:30) >= HOUR(products.Start) -- here is where the time is set
AND HOUR(18:30) <= HOUR(products.End) --and here is the end
)
ORDER BY products.Price/products.Multiple ASC;
I have as well tried BETWEEN query, and yet it does not work for those specific cases.

Basically, when products.End is smaller than products.Start, just add 24 to account for the day wrapping. E.g.
SELECT * FROM products
JOIN restaurants
ON (products.Venue = restaurants.name)
WHERE products.Drink_Category = Beer
AND restaurants.Area = Racks
AND (
HOUR(18:30) >= HOUR(products.Start) -- here is where the time is set
AND HOUR(18:30) <= CASE
WHEN products.End<products.Start
THEN HOUR(products.End)+24
ELSE HOUR(products.End) END --and here is the end
)
ORDER BY products.Price/products.Multiple ASC;

you have 2 way:
1- use complete date time value in your Condition like this:
Select * FROM table_event where ((SaleDate >= #FromDate) AND (SaleDate < #ToDate)) Order by SaleDate DESC
2- you can change your condition in back end, if your end time go to tomorrow you must write another condition like this:
(HOUR(18:30) >= HOUR(products.Start) AND HOUR(23:59) <= HOUR(products.End) )
OR
( HOUR(00:00) >= HOUR(products.Start) AND HOUR(3:00) <= HOUR(products.End) )

Related

Why this WHERE condition that have to select records in a specified timeframe is not working as expected?

I am not so into database and I have the following problem working on this MySql query:
SELECT
CCMD.id AS crop_calendar_message_details_id,
CCMD.broadcasting_start_date AS broadcasting_start_date,
CCMD.broadcasting_end_date AS broadcasting_end_date,
CCMD.creation_date AS creation_date,
CCM.id AS message_id,
CCM.content_en AS content_en,
IFNULL(CCMN.content, CCM.content_en) AS content,
CCMN.audio_link AS audio_link,
CCMD.crop_action_details_id AS crop_action_details_id
FROM CropCalendarMessageDetails AS CCMD
INNER JOIN CropCalendarMessage AS CCM
ON CCMD.crop_calendar_message_id = CCM.id
LEFT JOIN CropCalendarMessageName AS CCMN
ON CCMN.crop_calendar_message_id = CCM.id AND CCMN.language_id = :language_id
INNER JOIN CropActionDetails AS CAD
ON CCMD.crop_action_details_id = CAD.id
WHERE
CCMD.commodity_id = 10
AND
CCMD.country_id = 2
AND
CAD.id = :cad_id
AND
CCMD.broadcasting_start_date >= CURDATE()
AND
CURDATE() <= CCMD.broadcasting_end_date
ORDER BY CCMD.broadcasting_start_date
I have some records that have the following fixed values for thes date fields:
CCMD.broadcasting_start_date = 22/12/2018 23:59:00
CCMD.broadcasting_end_date = 30/05/2018
So in theory my query should skip these values because I have set this section on my WHERE clause:
AND
CCMD.broadcasting_start_date >= CURDATE()
AND
CURDATE() <= CCMD.broadcasting_end_date
The problem is that these records are returned by my query so this dates filter condition is not working.
Why? What is wrong? What am I missing? How can I fix it?
When dealing with date/time values and querying, I personally have always tried to apply >= and < the boundaries. For example, if you wanted something for All activity within March, 2018, I would do
where '2018-03-01' <= DateTimeField
AND DateTimeField < '2018-04-01'
By doing greater or equal to the start of just a date, you get from midnight all the way through the date period. As for the ending date, I always go LESS than the following day (hence April 1st). So I get everything up to Mar 31 at 11:59:59pm.
This way you also dont need to mess with date conversion functions just to ensure something is on the same day or time-portions thereof.
Might this help in resolving the date/time considerations of your query.

How to get the record of employees who were joined in first quarter or first month

I want to retrieve the records of employees who were joined in first quarter or in the first month. I have tried this but am not getting the right answer...
SELECT * FROM table
WHERE DOJ(date_created) = DOJ(CURRENT_DATE - INTERVAL 1 MONTH)
Please help me with this!
Answering the question as clarified in a comment...
SELECT * FROM table
WHERE YEAR(table.doj) = 2015 AND QUARTER(table.doj) = 1
If instead you want "first quarter of prior year"...
SELECT * FROM table
WHERE YEAR(table.doj) = YEAR(CURRENT_DATE) - 1 AND QUARTER(table.doj) = 1
In either case, note that there's no code to include the first month, because that's part of the first quarter. However, if you wanted to make that explicit (at a slight performance hit), you could code it as follows...
SELECT * FROM table
WHERE YEAR(table.doj) = 2015 AND (QUARTER(table.doj) = 1
OR MONTH(table.doj) = 1)
If you run into performance problems because you have a lot of records but only an index on table.doj, you could also write the query over an explicit date range...
SELECT * FROM table
WHERE table.doj >= '2015-01-01' AND table.doj <= '2015-03-31'

datetime select with -15 minute interval showing wrong result

For a room reservation page I'm making a query for entries among 3 tables. Datetime values are in one table, another table keeps the info if the room key has been checked out. And another table keeps the reservation information. If current time has past start of reservation time at least 15 minutes and the key has not been checked out, the entry should get deleted. Problem is, it deletes also future reservations, where the start time of the reservation has not past yet. My query looks like this.
SELECT dt.field_reservation_datetime_value
, dt.entity_id
, co.field_reservation_checked_out_value
, co.entity_id
, res.reservation_id
FROM field_data_field_reservation_datetime dt
JOIN field_data_field_reservation_checked_out co
ON co.entity_id = dt.entity_id
JOIN studyroom_reservation res
ON res.reservation_id = co.entity_id
WHERE co.field_reservation_checked_out_value = 0
AND DATE (dt.field_reservation_datetime_value) <= NOW() - INTERVAL 15 MINUTE
Right now it is 9:52am, this shouldn't be showing up for the next 2 hours and 38 minutes. What I get is this:
Any idea what I may doing wrong?
edit: table alias added and screenshot
Solved it with following code
SELECT dt.*, co.*, res.*
FROM field_data_field_reservation_datetime AS dt
JOIN field_data_field_reservation_checked_out AS co
ON co.entity_id = dt.entity_id
JOIN studyroom_reservation as res
ON res.reservation_id = co.entity_id
WHERE co.field_reservation_checked_out_value = 0
AND ((dt.field_reservation_datetime_value)
<= DATE_FORMAT(NOW() - INTERVAL 15 MINUTE,'%Y-%m-%d %H:%i:%s'))

SQL Statement Database

I have a Mysql Table that holds dates that are booked (for certain holiday properties).
Example...
Table "listing_availability"
Rows...
availability_date (this shows the date format 2013-04-20 etc)
availability_bookable (This can be yes/no. "Yes" = the booking changeover day and it is "available". "No" means the property is booked for those dates)
All the other dates in the year (apart from the ones with "No") are available to be booked. These dates are not in the database, only the booked dates.
My question is...
I have to make a SQL Statement that first calls the Get Date Function (not sure if this is correct terminology)
Then removes the dates from "availability_date" WHERE "availability_bookable" = "No"
This will give me the dates that are available for bookings, for the year, for a property.
Can anyone help?
Regards M
Seems like you've almost written the query.
SELECT availability_date FROM listing_availability
WHERE availability_bookable <> 'NO'
AND availability_date >= CURDATE()
AND YEAR(CURDATE()) = YEAR(availability_date)
I think I understand, and you'll obviously confirm. Your "availability_booking" has some records in it, but not every single day of the year, only those that may have had something, and not all are committed, some could have yes, some no.
So, you want to simulate All dates within a given date range... Say April 1 - July 1 as someone is looking to book a party within that time period. Instead of pre-filling your production table, you can't say that April 27th is open and available... since no such record exists.
To SIMULATE a calendar of days for a date range, you can do it using MySQL variables and join to "any" table in your database provided it has enough records to SIMULATE the date range you want...
select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DatesForAvailabilityCheck
from
( select #myDate := '2013-03-31' ) as SQLVars,
AnyTableThatHasEnoughRows
limit
120;
This will just give you a list of dates starting with April 1, 2013 (the original #myDate is 1 day before the start date since the field selection adds 1 day to it to get to April 1, then continues... for a limit of 120 days (or whatever you are looking for range based -- 30days, 60, 90, 22, whatever). The "AnyTableThatHasEnoughRows" could actually be your "availability_booking" table, but we are just using it as a table with rows, no join or where condition, just enough to get ... 120 records.
Now, we can use this to join to whatever table you want and apply your condition. You just created a full calendar of days to compare against. Your final query may be different, but this should get it most of the way for you.
select
JustDates.DatesForAvailabilityCheck,
from
( select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DatesForAvailabilityCheck
from
( select #myDate := '2013-03-31' ) as SQLVars,
listing_availability
limit
120 ) JustDates
LEFT JOIN availability_bookable
on JustDates.DatesForAvailabilityCheck = availability_bookable.availability_date
where
availability_bookable.availability_date IS NULL
OR availability_bookable.availability_bookable = "Yes"
So the above uses the sample calendar and looks to the availability. If no such matching date exists (via the IS NULL), then you want it meaning there is no conflict. However, if there IS a record in the table, you only want those where YES, you CAN book it, the entry on file might not be committed and CAN be in your result query of available dates.

Repeating calendar events and some final maths

I am trying to have a go at the infamous repeating events on calendars using PHP/MySQL. I've finally found something that seems to work. I found my answer here but I'm having a little difficulty finishing it off.
My first table 'events'.
ID NAME
1 Sample Event
2 Another Event
My second table 'events_meta that stores the repeating data.
ID event_id meta_key meta_value
1 1 repeat_start 1336312800 /* May 7th 2012 */
2 1 repeat_interval_1 432000 /* 5 days */
With repeat_start being a date with no time as a unix timestamp, and repeat_interval an amount in seconds between intervals (432000 is 5 days).
I then have the following MySQL which I modified slightly from the above link. The timestamp used below (1299132000 which is 12th May 2012) is the current day with no time.
SELECT EV.*
FROM `events` EV
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
RIGHT JOIN `events_meta` EM2 ON EM2.`meta_key` = CONCAT( 'repeat_interval_', EM1.`id` )
WHERE EM1.meta_key = 'repeat_start'
AND (
( CASE ( 1336744800 - EM1.`meta_value` )
WHEN 0
THEN 1
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
END
)
) = 1
In the above MySQL, the following code deducts the repeat_start field (EM1.'meta_value') from the current date and then divides it by the repeat interval field (EM2.'meta_value').
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
OR
TODAYS DATE - START DATE / 5 DAYS
So here's the maths:
1336744800 - 1336312800 = 432000
432000 / 432000 = 1
Now that works perfect. But if I change the current timestamp 5 days ahead to 1336312800 which is 17th Mat 2012, it looks a bit like this:
1336312800 - 1336312800 = 864000
86400 / 432000 = 2
Which doesn't work because it equals 2 and in the MySQL it needs to equal 1. So I guess my question is, how do I get the MySQL to recognise a whole number rather than having to do this?
...
WHERE EM1.meta_key = 'repeat_start'
AND (
( CASE ( 1336744800 - EM1.`meta_value` )
WHEN 0
THEN 1
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
END
)
) = IN (1,2,3,4,5,6,7,8,....)
Hope I'm making sense and I hope it's just a simple maths thing or a function that MySQL has that will help :) Thanks for your help!
EDIT: THE ANSWER
Thanks to #eggypal below, I found my answer and of course it was simple!
SELECT EV.*
FROM elvanto_calendars_events AS EV
RIGHT JOIN elvanto_calendars_events_meta AS EM1 ON EM1.`event_id` = EV.`id`
RIGHT JOIN elvanto_calendars_events_meta AS EM2 ON EM2.`meta_key` = CONCAT( 'repeat_interval_', EM1.`id` )
WHERE EM1.meta_key = 'repeat_start'
AND ( ( 1336744800 - EM1.`meta_value` ) % EM2.`meta_value`) = 0
It's not entirely clear what you want your query to do, but the jist of your question makes me lean toward suggesting that you look into modular arithmetic: in SQL, a % b returns the remainder when a is divided by b - if there is no remainder (i.e. a % b = 0), then a must be an exact multiple of b.
In your case, I think you're trying to find events where the time between the event start and some given literal is an exact multiple of the event interval: that is, (literal - event_start) % event_interval = 0. If it's non-zero, the value is the time to the next occurrence after literal (and, therefore, to determine whether that next occurrence occurs within some period of time, say a day, one would test to see if the remainder is less than such constant e.g. (literal - event_start) % event_interval < 86400).
If this isn't what you're after, please clarify exactly what your query is trying to achieve.
set #dat_ini = '2023-05-20',#dat_fim = '2022-11-20'; select (DATEDIFF( #dat_fim,#dat_ini )) % 60
THIS < 10
It only works for a short period.
To do this, take the start date and change the Month that is on the screen and add a year, then subtract it from the start date, then it works.