I have a column of type "datetime" with values like 2009-10-20 10:00:00
I would like to extract date from datetime and write a query like:
SELECT * FROM
data
WHERE datetime = '2009-10-20'
ORDER BY datetime DESC
Is the following the best way to do it?
SELECT * FROM
data
WHERE datetime BETWEEN('2009-10-20 00:00:00' AND '2009-10-20 23:59:59')
ORDER BY datetime DESC
This however returns an empty resultset. Any suggestions?
You can use MySQL's DATE() function:
WHERE DATE(datetime) = '2009-10-20'
You could also try this:
WHERE datetime LIKE '2009-10-20%'
See this answer for info on the performance implications of using LIKE.
Using WHERE DATE(datetime) = '2009-10-20' has performance issues. As stated here:
it will calculate DATE() for all rows, including those that don't match.
it will make it impossible to use an index for the query.
Use BETWEEN or >, <, = operators which allow to use an index:
SELECT * FROM data
WHERE datetime BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59'
Update: the impact on using LIKE instead of operators in an indexed column is high. These are some test results on a table with 1,176,000 rows:
using datetime LIKE '2009-10-20%' => 2931ms
using datetime >= '2009-10-20 00:00:00' AND datetime <= '2009-10-20 23:59:59' => 168ms
When doing a second call over the same query the difference is even higher: 2984ms vs 7ms (yes, just 7 milliseconds!). I found this while rewriting some old code on a project using Hibernate.
You can format the datetime to the Y-M-D portion:
DATE_FORMAT(datetime, '%Y-%m-%d')
Though all the answers on the page will return the desired result, they all have performance issues. Never perform transformations on fields in the WHERE clause (including a DATE() calculation) as that transformation must be performed on all rows in the table.
The BETWEEN ... AND construct is inclusive for both border conditions, requiring one to specify the 23:59:59 syntax on the end date which itself has other issues (microsecond transactions, which I believe MySQL did not support in 2009 when the question was asked).
The proper way to query a MySQL timestamp field for a particular day is to check for Greater-Than-Equals against the desired date, and Less-Than for the day after, with no hour specified.
WHERE datetime>='2009-10-20' AND datetime<'2009-10-21'
This is the fastest-performing, lowest-memory, least-resource intensive method, and additionally supports all MySQL features and corner-cases such as sub-second timestamp precision. Additionally, it is future proof.
Here are all formats
Say this is the column that contains the datetime value, table data.
+--------------------+
| date_created |
+--------------------+
| 2018-06-02 15:50:30|
+--------------------+
mysql> select DATE(date_created) from data;
+--------------------+
| DATE(date_created) |
+--------------------+
| 2018-06-02 |
+--------------------+
mysql> select YEAR(date_created) from data;
+--------------------+
| YEAR(date_created) |
+--------------------+
| 2018 |
+--------------------+
mysql> select MONTH(date_created) from data;
+---------------------+
| MONTH(date_created) |
+---------------------+
| 6 |
+---------------------+
mysql> select DAY(date_created) from data;
+-------------------+
| DAY(date_created) |
+-------------------+
| 2 |
+-------------------+
mysql> select HOUR(date_created) from data;
+--------------------+
| HOUR(date_created) |
+--------------------+
| 15 |
+--------------------+
mysql> select MINUTE(date_created) from data;
+----------------------+
| MINUTE(date_created) |
+----------------------+
| 50 |
+----------------------+
mysql> select SECOND(date_created) from data;
+----------------------+
| SECOND(date_created) |
+----------------------+
| 31 |
+----------------------+
You can use:
DATEDIFF ( day , startdate , enddate ) = 0
Or:
DATEPART( day, startdate ) = DATEPART(day, enddate)
AND
DATEPART( month, startdate ) = DATEPART(month, enddate)
AND
DATEPART( year, startdate ) = DATEPART(year, enddate)
Or:
CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))
simple and best way to use date function
example
SELECT * FROM
data
WHERE date(datetime) = '2009-10-20'
OR
SELECT * FROM
data
WHERE date(datetime ) >= '2009-10-20' && date(datetime ) <= '2009-10-20'
I tried date(tscreated) = '2022-06-04' on a large record set. My tscreated is indexed. It took 42 seconds.
I then tried tscreated >= '2022-06-04' and tscreated < '2022-06-05' and the time was .094 sec.
I realize that the record set might be in memory the second time, but I also believe that the date function negates the value of the index.
Well, using LIKE in statement is the best option
WHERE datetime LIKE '2009-10-20%'
it should work in this case
Related
I have a table that has a column row filled with a Javascript's, Date.now() function.
The column name is update_time, and its sample value is 1571152209099.
How can I make a Select for all rows that have todays date (taking into account only year, month and a day)?
I have tried something like this, but it get's me nowhere.
Select *
from program_end
where workout_rate between 0 and 1
AND FROM_UNIXTIME(update_time, '%YYYY-%MM-%DD') = CURDATE()
I also tried changing the time format:
Select *
from program_end
where FROM_UNIXTIME(update_time, '%Y-%m-%d') = CURDATE()
But no result whatsoever.
Any insight is appreciated.
For insight, consider:
SELECT '1970-01-01' + INTERVAL ( 1571152209099 /1000) SECOND
returns:
_dt
--------------------------
2019-10-15 15:10:09.099000
We recognize that the 1571152209099 value from JavaScipt Date.now() is integer milliseconds from the beginning of the era (Jan 1, 1970 midnight UTC).
Also consider:
SELECT TIMESTAMPDIFF(SECOND,'1970-01-01 00:00','2019-10-15 00:00')*1000 AS _dt_1
, TIMESTAMPDIFF(SECOND,'1970-01-01 00:00','2019-10-16 00:00')*1000 AS _dt_2
returns:
_dt_1 _dt_2
------------- --------------
1571097600000 1571184000000
The TIMESTAMPDIFF function is returning a difference in seconds; we multiply by 1000 to get milliseconds.
We recognize that any JavaScript Date.now() milliseconds value that is greater than or equal to _dt_1 and is less than _dt_2 occurs sometime "on" the date '2109-10-15'
So, given update_time is milliseconds since the beginning of the era...
In a query, I would compare the bare update_time column to two literal values:
WHERE update_time >= 1571097600000
AND update_time < 1571184000000
Referencing the bare column has the advantage that MySQL can make use of an efficient range scan operation, with a suitable index available.
To derive those millisecond values from a given date value, we can do a calculation in an expression, like this:
WHERE update_time >= TIMESTAMPDIFF(SECOND,'1970-01-01', '2019-10-15' )*1000
AND update_time < TIMESTAMPDIFF(SECOND,'1970-01-01', '2019-10-15' + INTERVAL 1 DAY)*1000
^^^^^^^^^^
Those expressions on the right side get evaluated just one time at the start of the statement execution.
Note that if we wrap update_time in a function, then that function has to be evaluated for every value of update_time, for every row in the table (that isn't filtered out by some other predicate.)
If you don't have dates in the future, you can simply do:
WHERE update_time >= UNIX_TIMESTAMP(CURDATE())
This will happily use an existing index on update_time.
If you have dates in the future that you need to exclude from the resultset, then:
WHERE
update_time >= UNIX_TIMESTAMP(CURDATE())
AND update_time < UNIX_TIMESTAMP(CURDATE() + INTERVAL 1 DAY)
Javascript's Date.now is giving you milliseconds, whereas MySQL's FROM_UNIXTIME expects seconds.
Unable to understand the epoch timestamp in milliseconds, FROM_UNIXTIME is returning NULL, which is of course failing to match the current date.
mysql> SELECT FROM_UNIXTIME(1571152209099);
+------------------------------+
| FROM_UNIXTIME(1571152209099) |
+------------------------------+
| NULL | -- THIS IS YOUR PROBLEM
+------------------------------+
1 row in set (0.00 sec)
mysql> SELECT FROM_UNIXTIME(1571152209099/1000);
+-----------------------------------+
| FROM_UNIXTIME(1571152209099/1000) |
+-----------------------------------+
| 2019-10-15 10:10:09.0990 |
+-----------------------------------+
1 row in set (0.00 sec)
Try this:
FROM_UNIXTIME(FLOOR(update_time/1000), format...)
Hello i need expert advice for my mysql query
I'm trying to filter values between 2 months
If start day lower then end day of different months all working well
But if i try higher day value on start return none
this is working code
SELECT id, teslim_tarihi AS tarih, toplam, marka, model, malzeme
FROM ariza
WHERE durum = '7' AND (teslim_tarihi BETWEEN '01-02-2018 00:00' AND '01-03-2018 23:59')
ORDER BY tarih DESC
Not working at all
SELECT id,teslim_tarihi as tarih ,toplam,marka,model,malzeme
FROM ariza
WHERE durum = '7' AND (teslim_tarihi BETWEEN '14-02-2018 00:00' AND '01-03-2018 23:59')
ORDER BY tarih DESC
date format dd-mm-yyyy H:i
As has been suggested by #stackFan, it really does make considerable sense to stick with mysql's default date and time formats. However, for whatever reason, you seem to be stuck with a different format so I'll attempt to work with that.
Your current query isn't working in your second example because mysql doesn't recognise these as dates and a strings starting '14-02-2018' is greater than another string starting '01-03-2018'. e.g.
SELECT '14-02-2018' > '01-03-2018';
+-----------------------------+
| '14-02-2018' > '01-03-2018' |
+-----------------------------+
| 1 |
+-----------------------------+
The values when using BETWEEN ... AND have to have the min value first and the max value Documentation, so in your second example the comparison is the wrong way round because '14-02-2018' is greater than '01-03-2018', hence no rows returned.
You didn't answer the query about the data type of your column teslim_tarihi which would have made answering your query simpler. I'll assume it is a DATETIME or TIMESTAMP. Your comparison should be made against something that mysql knows to be a date or recognises as a date and that means getting the dates into YYYY-MM-DD or YY-MM-DD format. Mysql will helpfully cast values to the appropriate type if the format is one it recognises. e.g.
SELECT DATE '2018-02-14' < '2018-03-01';
+-----------------------------------+
| DATE '2018-02-14' < '2018-03-01' |
+-----------------------------------+
| 1 |
+-----------------------------------+
You should be able to get the query working by turning your strings into dates in the following manner.
SELECT DATE '2018-03-01'
BETWEEN STR_TO_DATE('14-02-2018 00:00', '%d-%m-%Y %H:%i')
AND STR_TO_DATE('01-04-2018 23:59','%d-%m-%Y %H:%i') 'between dates';
+---------------+
| between dates |
+---------------+
| 1 |
+---------------+
If your column teslim_tarihi is a VARCHAR, then convert that in the same manner to get the query to work.
As per the documentation the default format of date in MySQL is YYYY-MM-DD. Can you try using this query instead?
SELECT id,teslim_tarihi as tarih ,toplam,marka,model,malzeme
FROM ariza
WHERE durum = '7' AND (teslim_tarihi BETWEEN '2018-02-14 00:00:00' AND '2018-03-01 23:59:59')
ORDER BY tarih DESC
This is really simple yet I always struggle with it. I need help getting records before midnight:
AND last_checked < date('2013-06-25 00:00:00'))
This obviously doesn't work, since its string evaluation. I do not want to restrict it to this year and put a between in the code. Any help is extremely appreciated :)
You can also do this in a generic way
AND last_checked < ( DATE(NOW()) + INTERVAL 0 SECOND );
Watch this:
mysql> SELECT DATE(NOW()) + INTERVAL 0 SECOND Midnight;
+---------------------+
| Midnight |
+---------------------+
| 2013-06-25 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
mysql>
You should be able to just do
AND last_checked < '2013-06-25 00:00:00'
Using the date() function just extracts the date part of the argument.
If last_checked is of datetime data type, then your WHERE clause will look like this:
WHERE ...
AND cast (last_checked as date) = '2013-06-25'
CAST (datetime as date) drops time part, so you can easily get all data between 00h:00m:00s and 23h:59m:59s .
My NOW Function is not working the way I want it to. I just want to simply find dates that are past todays date.
Here is my query.
SELECT *
FROM `trade_show_inventory`
LEFT JOIN `trade_show_reserved`
ON `trade_show_inventory`.`id` = `trade_show_reserved`.`productid`
WHERE `trade_show_inventory`.`quantity` > 0
OR `trade_show_reserved`.`datereserved`
+ INTERVAL 5 day <= '2013-03-31'
AND `trade_show_reserved`.`datereserved` > Now()
EDIT:
I changed my query to this and it still is not working. Still working away at it..
$date = date('Y-m-d');
$sql = "SELECT * FROM `trade_show_inventory` LEFT JOIN `trade_show_reserved`
ON `trade_show_inventory`.`ID` = `trade_show_reserved`.`ProductID`
WHERE (`trade_show_inventory`.`Quantity` > 0)
or (`trade_show_reserved`.`DateReserved` + INTERVAL 5 DAY <= '$setupStart' and
`trade_show_reserved`.`DateReserved` > '2013-03-25')";
Well, your where clause is parsing like:
WHERE (`trade_show_inventory`.`Quantity` > 0) or
(`trade_show_reserved`.`DateReserved` + INTERVAL 5 DAY <= '2013-03-25' and
`trade_show_reserved`.`DateReserved` > NOW()
)
If the date is five days before 2013-03-25, then it can't be in the future (as of today at least).
Put parentheses around the where clauses to get the logic you intend.
NOW() doesn't return a date... it's a complete timestamp:
mysql> select NOW();
+---------------------+
| NOW() |
+---------------------+
| 2013-03-25 17:20:06 |
+---------------------+
1 row in set (0.00 sec)
Try wrapping the DATE function around it:
mysql> select DATE(NOW());
+-------------+
| DATE(NOW()) |
+-------------+
| 2013-03-25 |
+-------------+
1 row in set (0.00 sec)
NOW() returns the current date & time.
You would perhaps want to use DATE() as it returns the date without time.
The NOW() function uses timestamp, i think you should first convert it into a date format that you require.
How to pass the current date to a query in mysql like such query:
select from Dailytimesheet dailytimesheet where dailytimesheet.TrackingDate="2010-05-03"
In MySQL, you can use CURRENT_DATE to get the current date.
mysql> select CURRENT_DATE;
+--------------+
| CURRENT_DATE |
+--------------+
| 2010-05-03 |
+--------------+
1 row in set (0.08 sec)
Using NOW() works as well, but gets you the current date and time as a timestamp value. You can truncate it like DATE(NOW()), but CURRENT_DATE avoids the function call.
you can use the NOW() function within your SQL query to get the current timestamp.