This is a tough one i'm trying to figure out.
This is my table:
task_reminders
- id
- date
- time
I want to SELECT ALL rows which has a date and time 3 hours after the current (NOW) date and time (UTC). It is tough because the date and time columns are separate.
Examples:
For example, if the current date and time is 2019-01-20 08:30:00, I want to select all rows that have a date and time that is 3 hours after that time (only counting hours).
2019-01-20 11:50:00 this would work
2019-01-20 11:10:00 this would work too
2019-01-20 10:00:00 would NOT work
2019-01-20 12:00:00 would NOT work
Another example: If the current date and time is 2019-01-19 11:20:00, these would and would not work:
2019-01-20 02:50:00 this would work
2019-01-20 02:30:00 this would work too
2019-01-20 01:10:00 would NOT work
2019-01-20 03:45:00 would NOT work
It is kind of hard because the DATE and TIME are separate in my database. How would i do this? Thank you!
Since you just want the hours to be different from each other by 3, you can check for 2 conditions:
HOUR(NOW()) is < 21, in which case the dates should be the same and HOUR(time) = HOUR(NOW()) + 3; or
HOUR(NOW()) >= 21, in which case the date should be 1 more than CURDATE() and HOUR(time) =HOUR(NOW()) - 21`
So your query would be:
SELECT *
FROM task_reminders
WHERE HOUR(`time`) = HOUR(NOW()) + 3 AND `date` = CURDATE() OR
HOUR(`time`) = HOUR(NOW()) - 21 AND `date` = CURDATE() + INTERVAL 1 DAY
Note
Since hours wrap, there is no need to include the conditions about HOUR(NOW()) relative to 21 in the query
I'm assuming your date and time columns are of datatype DATE and TIME respectively.
Checkout this it will compare date and hour but skip time and seconds as you want
SELECT *
FROM task_reminders
WHERE DATE_FORMAT(CAST(CONCAT(`edate`, ' ', `etime`) AS DATETIME), '%Y-%m-%d %H') >=
DATE_FORMAT(DATE_ADD(NOW(), INTERVAL 3 HOUR) , '%Y-%m-%d %H')
Please check sqlfiddle at http://www.sqlfiddle.com/#!9/9bec7a/1
Use this query and replace the table and variable names
$result = mysqli_query($con,"SELECT sent_date FROM invitations WHERE email='$email' AND uid='$session_uid' AND `sent_date` < SUBDATE( CURRENT_DATE, INTERVAL 3 HOUR)");
Related
I'm trying to do a query in MYSQL selecting orders where the created_at datetime is between the previous 3:00 in the morning and the next 3:00 in the morning.
For example: if I make that query at 2020-03-31 11:00:00, it should show me all the orders where the created_at timestamp are between 2020-03-31 03:00:00 and 2020-04-01 03:00:00.
I've tried to make this by using this query:
select *
from "orders"
where "created_at" BETWEEN cast(curdate() as datetime) + interval 3 hour
and cast(curdate() as datetime) + interval 1 day + interval 3 hour
but that doesn't work correctly because if i execute this query between 0:00 and 3:00 in the morning (For example at 2020-03-31 00:30:00), it won't show anything, but it should show me all the orders where the created_at timestamp are between 2020-03-30 03:00:00 and 2020-03-31 03:00:00.
Any idea of how to do that? I've been trying to find a solution for 2 hours a i couldn't find the right query to do so.
I would do:
created at >= date(now()- interval 3 hour) + interval 3 hour
and created_at < date(now()- interval 3 hour) + interval 3 hour + interval 1 day
The logic is to offset the current date and time by 3 hours, remove the time component, and then add 3 hours.
Then you could do
select ...
where `created_at` BETWEEN DATE_SUB(concat(CURDATE(), ' 03:00:00'), INTERVAL 1 DAY)
AND concat(CURDATE(), ' 03:00:00');
I am working on to get records from last 13 months using following MySQL query:
SELECT YEAR(`customer_date`),
MONTHNAME(`customer_date`),
COUNT(`customer_date`) AS Enquiries
FROM `crm_customers`
WHERE DATE(`customer_date`) BETWEEN CURRENT_DATE - INTERVAL 13 month AND
CURRENT_DATE
GROUP BY YEAR(`customer_date`),
MONTH(`customer_date`)
ORDER BY YEAR(`customer_date`) DESC,
MONTH(`customer_date`) DESC
My prototype MySQL table crm_customers looks as:
customer_id customer_date
1 2019-02-01 00:00:00
2 2019-02-02 00:00:00
... ...
... ...
... ...
Output:
Though above query does work fine and gives me almost correct result set except one issue related to very last month of the last year from a gap of 13 months from today.
Today is 7th of March 2020. The date condition in my above query
WHERE DATE(`customer_date`) BETWEEN CURRENT_DATE - INTERVAL 13 month AND CURRENT_DATE
starts fetching the result from 7th of Feb 2019.
In the month of Feb, 2019 I have 104 entries. But my above SQL fetches only 80 entries because 24 entries are before 07-Feb-2019 (between 1 Feb and 6 Feb 2019). I want to include those entries as well. How can I modify my date condition to achieve the required result.
EDIT
Why this question is marked negative? I don't understand. Question is very much clear and not duplicated. Is it down voted by GMB?
change your WHERE clause to:
WHERE DATE(`customer_date`) BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01') - INTERVAL 13 month AND DATE_FORMAT(NOW() ,'%Y-%m-01')
There are some possibility to achieve this
SELECT CURDATE()
, CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE)
,LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY;
Results in
CURDATE() , CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE), LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY
2020-03-07, 2020-03-01 , 2020-03-01
Sounds like you want to reduce precision in your DATE value. Use EXTRACT() for this;
EXTRACT(YEAR_MONTH FROM CURDATE() - INTERVAL 13 MONTH)
I would suggest:
where
customer_date >= date_format(current_date, '%Y-%m-01') - interval 13 month
and customer_date < current_date + interval 1 day
Rationale:
this compares the stored date without prior transformation (while your query, and all answers so far, use date()), which makes it possible to benefit an existing index - on a large dataset, this can make a big performance difference
date arithmetics is as simple as possible; MySQL happily treats strings in proper formats as dates, which can shorten the syntax
I'm using this query to calculate the login time of a user on the app for the whole day and previous 5 days
Select
sec_to_time(sum(time_to_sec(TIMEDIFF((IFNULL(logoff_time, ADDTIME(now(), '05:00:00'))),login_time)))) as online_time
from tb_sessions
WHERE
(login_time BETWEEN DATE(DATE_ADD(now(), INTERVAL (-6) DAY))
AND
ADDTIME(now(), '5:00:00')) AND user_id = 30982
AND TIME(`login_time`) between "00:00:00" AND "23:59:59"
group by DATE(login_time)
Now i have some new requirements:
Calculate time from 07:00:00 to 23:59:59
My Table: tb_sessions
id | user_id | login_time | logoff_time
1 3098 2017-06-10 06:30:00 2017-06-10 07:45:00
2 3098 2017-06-10 07:45:01 2017-06-10 08:30:00
By using above query total oline time is = 02:00:00
But i want only time from 7:00 to 8:30, so total time will be = 1:30:00
I make some changes in query with cases but no success.
You can check my query on the below link:
http://sqlfiddle.com/#!9/4620af/12
You could use greatest to take the latest of the dates login_time and 7:00 on the same day, and then use greatest again to exclude negative time differences (when also logoff time is before 7:00):
Select date(login_time) date,
time_format(sec_to_time(sum(greatest(0, time_to_sec(timediff(
ifnull(logoff_time, now()),
greatest(login_time, date_add(date(login_time), interval 7 hour))
))))), '%H:%i:%s') online
from tb_sessions
where login_time between date(date_add(now(), interval (-3) day)) and now()
and user_id = 3098
and time(login_time) between "00:00:00" and "23:59:59"
group by date(login_time)
See it run on sqlfiddle
Explanation
The inner greatest call looks like this:
greatest(login_time, date_add(date(login_time), interval 7 hour))
The second argument takes the date-only from the login_time, so it corresponds to midnight of that day, and then adds 7 hours to it: so this represents 7:00 on that day. greatest will return the latest of these two timestamps. If the first argument represents a time than 7:00, it will be returned. If not, the second argument (i.e. 7:00) will be returned.
The outer greatest call looks like this:
greatest(0, time_to_sec(timediff(....)))
This will make sure the time difference is not negative. Take this example record:
login_time | logoff_time
----------------+----------------
2017-06-01 6:30 | 2017-06-01 6:45
In this case the innermost greatest will return 2017-06-01 7:00, because 6:30 is too early. But that will make timediff() return a negative time interval: -15 minutes. What we really want is 0, because there is no time the user was logged on after 7:00. This is what greatest will do: greatest(0, -15) = 0, so the negative value will be eliminated and will not influence the sum.
Condition on login_time
I left the condition time(login_time) between "00:00:00" and "23:59:59" there, but it really does not do anything, since that is true for all times (unless they are null, but then they would not pass the first condition either).
Edit after New Requirements
In comments you asked how to group by each day when a user doesn't log off on the same day but stays online until 1 or 2 days later.
In that case you need a helper table that will list all days you want to see in the output. This could for instance be seven records for the 7 last days.
Then you have to join your table with it so that there is at least an overlap of the user's session with such a reference date. The calculation of the online time will have to take into account that the log off time might not be before mid night.
Here is the updated query:
select ref_date date,
time_format(sec_to_time(sum(greatest(0, time_to_sec(timediff(
least(ifnull(logoff_time, now()), date_add(ref_date, interval 1 day ), now()),
greatest(login_time, date_add(ref_date, interval 7 hour))
))))), '%H:%i:%s') online
from ( select date(date_add(now(), interval (-6) DAY)) as ref_date union all
select date(date_add(now(), interval (-5) DAY)) union all
select date(date_add(now(), interval (-4) DAY)) union all
select date(date_add(now(), interval (-3) DAY)) union all
select date(date_add(now(), interval (-2) DAY)) union all
select date(date_add(now(), interval (-1) DAY)) union all
select date(now())
) ref
inner join tb_sessions
on login_time < date_add(ref_date, interval 1 day)
and logoff_time > date_add(ref_date, interval 7 hour)
where user_id = 3098
group by ref_date
See it run on sqlfiddle.
I am trying to pickup 1 day previous records based on few dates and time stamps but my is not retrieving recorders from 00:00:00 to 23:59:00. I am using the follwoing criteria.
and ((cast(from_unixtime(schedule.last_change_timestamp) as date) = (curdate() - interval 1 day))
or (cast(schedule.date_added as date) = (curdate() - interval 1 day))
or (left(jobsheet.actual_completion_date_set, 10) = (curdate() - interval 1 day))
or (cast(from_unixtime(orders.dateadded) as date) = (curdate() - interval 1 day)))),
The records which I am missing are most likely related to jobsheet.actual_completion_date_set which is in this format
'yyyy-mm-dd hh:mm:ss' and I am using left 10 characters for interval. Please could someone provide some help as to how I can force all these dates to select all records from 00:00:00 to 23:59:00 the previous day.
Thanks,
Is this what you want?
left(jobsheet.actual_completion_date_set, 10) = date_format(date_sub(curdate(), interval 1 day, '%Y-%m-%d')
In MySQL, I find it safer to use date_sub() and date_add() for the built-in constants. These are not returned as datetime or date, so strange things can happen with conversions to the dates.
I have a table session_dates with some fields and a timestamp field named timestart.
What I would like to do is select all the records from my table where the field timestart (TIMESTAMP) is equal to 21 days from now.
Like for example if today is 27 januari -> 17 februari.
I know how I can select all between two dates.
My SQL Query for between 2 dates:
SELECT timestart, timefinish, sessionid
FROM sessions_dates
WHERE timestart BETWEEN UNIX_TIMESTAMP(NOW()) AND UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL 21 DAY))
But how to select equal to a date?
UPDATE:
I know now that I just have to use the = statement. But how can I test this? How do I know what the UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL 21 DAY)) returns?
I think you want:
SELECT timestart, timefinish, sessionid
FROM sessions_dates
WHERE timestart >= UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL 21 DAY)) AND
tmestamp < UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL 22 DAY))
Presumably, timestart has a time component. This version takes that into account and still would allow the use of an index on timestart.