MYSQL select date now-1 day with TIME and between date - mysql

I want to select all rows between current day-1 with specific time 08:00am and to date now also with specific time. This is not working for example sample line code
WHERE SOME_DATE_COLUMN BETWEEN DATE_SUB(DATE(NOW() - INTERVAL 1 DAY) '08:00:00', '%Y-%m-%d %H:%i:%s') AND DATE_SUB(DATE(NOW()) '08:00:00', '%Y-%m-%d %H:%i:%s');
I tried also DATE_FORMAT
WHERE SOME_DATE_COLUMN BETWEEN DATE_FORMAT(DATE(NOW() - INTERVAL 1 DAY) '08:00:00', '%Y-%m-%d %H:%i:%s') AND DATE_FORMAT(DATE(NOW()) '08:00:00', '%Y-%m-%d %H:%i:%s');
If I run sql today I want to select all record between current date minus 1 day from 08:00am to current date 08:00am

I would do:
where
some_date_column >= current_date - interval 16 hour
and some_date_column < current_date + interval 8 hour
current_date gives you the current date (without the time part). You can then add and substract the required number of hours.
Note that this query does not use between, but instead half-open intervals. If you want consistent, adjacent segments in time, then you want to exclude one of the bounds (by convention, generally the outer bound is excluded).
Demo on DB Fiddle:
select current_date - interval 16 hour, current_date + interval 8 hour
current_date - interval 16 hour | current_date + interval 8 hour
:------------------------------ | :-----------------------------
2020-02-04 08:00:00 | 2020-02-05 08:00:00

Related

MySQL - trying to select a range from the first day of previous month at midnight, to the first day of the current month at midnight

I'm working with MySQL, and attempting a specific time range query. For example if it's august now, I'm attempting to query from September 1st at midnight, to August 1st at midnight.
So far I'm able to get my date range successfully selected thanks to a prior question, but the problems I'm having are:
-My database columns for time are in UTC, and I need to convert to my timezone
-I'm having trouble adding the specific time into my query.
Here is my current query:
select column1,date_time_column from table.x
where date_time_column > concat(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day
and date_time_column < concat(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
order by date_time_column
;
I'm attempting to put my specific time as 05:00:00, which is midnight in my DB, but right now when I run my select, it's still showing 00:00:00 times, which makes me think my time isn't applying or I have my syntax for adding the time incorrect. Any help would be much appreciated.
Use DATE_FORMAT instead of CONCAT
SELECT
DATE_FORMAT(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day,
DATE_FORMAT(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
DATE_FORMAT(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day | DATE_FORMAT(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
:---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------
2021-07-01 05:00:00 | 2021-08-01 05:00:00
db<>fiddle here
select column1,date_time_column from table.x
where date_time_column > DATE_FORMAT(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day
and date_time_column < DATE_FORMAT(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
order by date_time_column
;

Better way to write a difference based date queries

I'm doing a review of existing code and have found the following SQL query which is used to get a selection of records last month.
Is there a more concise way of writing SQL to do what this date based clause does in MySQL?
SELECT foo
FROM some_table
WHERE some_date
BETWEEN
DATE_FORMAT(LAST_DAY((NOW() - INTERVAL 1 MONTH) - INTERVAL 1 SECOND), '%Y-%m-01 00:00:00')
AND
DATE_FORMAT(LAST_DAY((NOW() - INTERVAL 1 MONTH) - INTERVAL 1 SECOND), '%Y-%m-%d 23:59:59')
It works, but I just twitch a little every time I see it.
Can anyone else write it better?
Thank you in advance.
There's no need to format the dates, they default to YYYY-MM-DD 00:00:00.
This is a little bit simpler:
SELECT foo
FROM some_table
WHERE some_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
AND some_date < LAST_DAY(CURDATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY
So if CURDATE() is today, 2019-02-06, then:
- INTERVAL 2 MONTH is 2018-12-06
LAST_DAY() of that date is 2018-12-31
+ INTERVAL 1 DAY is 2019-01-01
Then the upper bound is:
- INTERVAL 1 MONTH is 2019-1-06
LAST_DAY() of that date is 2019-1-31
+ INTERVAL 1 DAY is 2019-02-01
The dates should be strictly less than 2019-02-01.
Using less than accounts for timestamps in the last second of the month, between 23:59:59.000 and 23:59:59.999.

Get results from whole hour 3 days ago

I have some table with a datetime column, and I want to fetch from it all results like this:
If I execute the query on 2016-01-28 11:12:24, I want to fetch all results from 3 days ago from that whole hour (11:00:00). So I'd get all rows between 2016-01-28 11:00:00 and 2016-01-28 11:59:59. How do I do this, so that I can benefit from index on this datetime column?
I have tried using WHERE DATE_FORMAT(o.created_at, '%Y-%m-%d %H:00:00') = DATE_FORMAT(NOW() INTERVAL -3 DAY, '%Y-%m-%d %H:00:00') but it is a function, so the query doesn't use an index.
The best solution is to do this:
WHERE o.created_at >= DATE_FORMAT(date_sub(now(), interval 3 day), '%Y-%m-%d %H:00:00') AND o.created_at < DATE_FORMAT(date_add(date_sub(now(), interval 3 day), interval 1 hour), '%Y-%m-%d %H:00:00')
Alternately, you can also do this but only with precision up to seconds:
WHERE o.created_at BETWEEN DATE_FORMAT(date_sub(now(), interval 3 day), '%Y-%m-%d %H:00:00') AND DATE_FORMAT(date_sub(now(), interval 3 day), '%Y-%m-%d %H:59:59')
The BETWEEN AND clause here still utilizes the Index as we have not used DATE_FORMAT function on the column o.created_at. It is also much more efficient if the selected data is less than 1/3rd of the total rows.
[Ref: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html ]
Note: Thanks to #Used_By_Already for pointing out the issue with precision up to microseconds.
Instead of formating a new date with NOW() Interval - 3...., take a look at DateDiff(). This allows you to set the difference from NOW() to other days and set the measure unit.

MYSQL one day interval from 00:00:00 to 23:59:00

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.

SQL Hourly Data

The query below retrieves weather data from a MySql database, and groups this data in to an hourly format.
select hour(datetime) AS hour
, avg(Temperature) as AVGT
from Database.minute
WHERE DATETIME
BETWEEN (CURDATE() + INTERVAL (SELECT hour(NOW())) hour - INTERVAL 23 hour)
AND ((CURDATE() + INTERVAL (SELECT hour(NOW())) hour))
group by hour
order by (CURDATE() + INTERVAL (SELECT hour(NOW())) hour - INTERVAL 23 hour)
Output is as follows:
hour AVGT
19 11.730
20 11.970
21 11.970
22 11.760
23 11.660
0 11.700
1 11.830
2 12.370
3 12.770
4 12.840
5 12.840
6 12.540
7 12.500
8 12.030
9 12.100
10 12.300
11 12.060
12 11.090
13 10.920
14 10.920
15 10.820
16 10.760
17 10.690
18 10.560
The time is now 18:15. All of the above output is correct apart from the data gathered for hour '18'. Instead of getting the average value between 18:00 and 18:15, it just outputs the average at time 18:00. ie. ignoring data between 18:01 and 18:14.
How can I modify the above query to include data in the current hour (18:00 to Now)?
Thanks
Why don't you simply try
SELECT Hour(datetime) AS hour,
Avg(temperature) AS AVGT
FROM DATABASE.minute
WHERE datetime BETWEEN ( Curdate() + INTERVAL (SELECT Hour(Now())) hour -
INTERVAL 23 hour ) AND Now()
GROUP BY hour
ORDER BY ( Curdate() + INTERVAL (SELECT Hour(Now())) hour - INTERVAL 23 hour )
I agree with #Ankur's answer (your filter citerion should not filter records up to the current hour, but rather the current time), however your date/time operations are very strange:
You don't need a subquery (SELECT Hour(NOW())) to obtain HOUR(NOW());
You can express ( Curdate() + INTERVAL (SELECT Hour(NOW())) hour - INTERVAL 23 hour ) more simply:
CURDATE() + INTERVAL HOUR(NOW()) - 23 HOUR
Or, in my view, more clearly:
DATE_FORMAT(NOW() - INTERVAL 23 HOUR, '%Y-%m-%d %H:00:00')
Your ORDER BY clause is a constant and therefore achieves nothing: did you mean to order by hour?
Therefore:
SELECT HOUR(datetime) AS hour,
AVG(Temperature) AS AVGT
FROM Database.minute
WHERE datetime BETWEEN
DATE_FORMAT(NOW() - INTERVAL 23 HOUR, '%Y-%m-%d %H:00:00')
AND NOW()
GROUP BY hour
ORDER BY hour