I am trying to select only today's records from a database table.
Currently I use
SELECT * FROM `table` WHERE (`timestamp` > DATE_SUB(now(), INTERVAL 1 DAY));
But this takes results for the last 24 hours, and I need it to only select results from today, ignoring the time. How can I select results based on the date only ?
use DATE and CURDATE()
SELECT * FROM `table` WHERE DATE(`timestamp`) = CURDATE()
Warning! This query doesn't use an index efficiently. For the more efficient solution see the answer below
see the execution plan on the DEMO
If you want an index to be used and the query not to do a table scan:
WHERE timestamp >= CURDATE()
AND timestamp < CURDATE() + INTERVAL 1 DAY
To show the difference that this makes on the actual execution plans, we'll test with an SQL-Fiddle (an extremely helpful site):
CREATE TABLE test --- simple table
( id INT NOT NULL AUTO_INCREMENT
,`timestamp` datetime --- index timestamp
, data VARCHAR(100) NOT NULL
DEFAULT 'Sample data'
, PRIMARY KEY (id)
, INDEX t_IX (`timestamp`, id)
) ;
INSERT INTO test
(`timestamp`)
VALUES
('2013-02-08 00:01:12'),
--- --- insert about 7k rows
('2013-02-08 20:01:12') ;
Lets try the 2 versions now.
Version 1 with DATE(timestamp) = ?
EXPLAIN
SELECT * FROM test
WHERE DATE(timestamp) = CURDATE() --- using DATE(timestamp)
ORDER BY timestamp ;
Explain:
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF
1 SIMPLE test ALL
ROWS FILTERED EXTRA
6671 100 Using where; Using filesort
It filters all (6671) rows and then does a filesort (that's not a problem as the returned rows are few)
Version 2 with timestamp <= ? AND timestamp < ?
EXPLAIN
SELECT * FROM test
WHERE timestamp >= CURDATE()
AND timestamp < CURDATE() + INTERVAL 1 DAY
ORDER BY timestamp ;
Explain:
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF
1 SIMPLE test range t_IX t_IX 9
ROWS FILTERED EXTRA
2 100 Using where
It uses a range scan on the index, and then reads only the corresponding rows from the table.
SELECT * FROM `table` WHERE timestamp >= CURDATE()
it is shorter , there is no need to use 'AND timestamp < CURDATE() + INTERVAL 1 DAY'
because CURDATE() always return current day
MySQL CURDATE() Function
Or you could use the CURRENT_DATE alternative, with the same result:
SELECT * FROM yourtable WHERE created >= CURRENT_DATE
Examples from database.guide
If you want to compare with a particular date , You can directly write it like :
select * from `table_name` where timestamp >= '2018-07-07';
// here the timestamp is the name of the column having type as timestamp
or
For fetching today date , CURDATE() function is available , so :
select * from `table_name` where timestamp >= CURDATE();
This could be the easiest in my opinion:
SELECT * FROM `table` WHERE `timestamp` like concat(CURDATE(),'%');
Simply cast it to a date:
SELECT * FROM `table` WHERE CAST(`timestamp` TO DATE) == CAST(NOW() TO DATE)
How many ways can we skin this cat? Here is yet another variant.
SELECT * FROM table WHERE DATE(FROM_UNIXTIME(timestamp)) = '2015-11-18';
On Visual Studio 2017, using the built-in database for development I had problems with the current given solution, I had to change the code to make it work because it threw the error that DATE() was not a built in function.
Here is my solution:
where CAST(TimeCalled AS DATE) = CAST(GETDATE() AS DATE)
SELECT * FROM table WHERE FROM_UNIXTIME(your_column_with_unix_time,'%Y-%m-%d') = CURDATE()
Related
What's the best way to do following:
SELECT * FROM users WHERE created >= today;
Note: created is a datetime field.
SELECT * FROM users WHERE created >= CURDATE();
But I think you mean created < today
You can compare datetime with date, for example: SELECT NOW() < CURDATE() gives 0, SELECT NOW() = CURDATE() gives 1.
SELECT * FROM myTable WHERE DATE(myDate) = DATE(NOW())
Read more:
http://www.tomjepson.co.uk/tutorials/36/mysql-select-where-date-today.html
SELECT * FROM users WHERE created >= NOW();
if the column is datetime type.
Answer marked is misleading. The question stated is DateTime, but stated what was needed was just CURDATE().
The shortest and correct answer to this is:
SELECT * FROM users WHERE created >= CURRENT_TIMESTAMP;
If 'created' is datetime type
SELECT * FROM users WHERE created < DATE_ADD(CURDATE(), INTERVAL 1 DAY);
CURDATE() means also '2013-05-09 00:00:00'
If the column have index and a function is applied on the column then index doesn't work and full table scan occurs, causing really slow query.
Bad Query; This would ignore index on the column date_time
select * from users
where Date(date_time) > '2010-10-10'
To utilize index on column created of type datetime comparing with today/current date, the following method can be used.
Solution for OP:
select * from users
where created > CONCAT(CURDATE(), ' 23:59:59')
Sample to get data for today:
select * from users
where
created >= CONCAT(CURDATE(), ' 00:00:00') AND
created <= CONCAT(CURDATE(), ' 23:59:59')
Or use BETWEEN for short
select * from users
where created BETWEEN
CONCAT(CURDATE(), ' 00:00:00') AND CONCAT(CURDATE(), ' 23:59:59')
Tip:
If you have to do a lot of calculation or queries on dates as well as time, then it's very useful to save date and time in separate columns. (Divide & Conquer)
SELECT * FROM users WHERE created >= now()
The below code worked for me.
declare #Today date
Set #Today=getdate() --date will equal today
Select *
FROM table_name
WHERE created <= #Today
SELECT * FROM table_name WHERE CONCAT( SUBSTRING(json_date, 11, 4 ) , '-', SUBSTRING( json_date, 7, 2 ) , '-', SUBSTRING(json_date, 3, 2 ) ) >= NOW();
json_date ["05/11/2011"]
you can return all rows and than use php datediff function inside an if statement, although that will put extra load on the server.
if(dateDiff(date("Y/m/d"), $row['date']) <=0 ){
}else{
echo " info here";
}
I currently run this operation to convert empty strings to null. Is any way to find out the last row that has gone through NULLIF() operation or has null character so I can process everything from that point. My table has a timestamp column. I have 150 columns like recovery_email and I'd like to start from the last empty string was found in either of them.
UPDATE table
SET recovery_email = NULLIF(recovery_email, ''), # There are 150 columns like recovery_email.
email = NULLIF(email, ''),
WHERE timestamp >= (NOW() - INTERVAL 1 DAY)
If none of your recovery_email is null before the update query is executed, you can run the following query after the update statement to get the timestamp of the last updated row:
select max(timestamp) last_timestamp
from mytable
where recovery_email is null and timestamp >= now() - interval 1 day
Otherwise, you need to compute the latest value before the update, with the following query:
select max(timestamp) last_timestamp
from mytable
where recovery_email = '' and timestamp >= now() - interval 1 day
This answers the original version of the question.
Why would you use NULLIF()? Just filter down to the rows you want:
UPDATE table
SET recovery_email = NULL
WHERE timestamp >= (NOW() - INTERVAL 1 DAY) AND recovery_email = '';
You can put an index on recovery_email and not worry about attempting to filter by time.
Or, better yet, defined the column with a check constraint (in the most recent versions of MySQL) so empty strings are not allowed.
I'm facing a strange mysql behavior...
If I want to return the rows from "MyTable" with a date lower than date-10 seconds ago or a future date
I also store future date because in my real program, I "launch" some queries with delay and date is actually the last query date...i.e.: a kind of queue...:
SELECT (NOW() - date) AS new_delay, id
FROM MyTable
WHERE (NOW() - date < 10)
ORDER BY new_delay DESC;
This one does not work as expected: It returns all the entries:
EDIT: here is the result:
However, this one is working just fine:
SELECT (NOW() - date) AS new_delay, id
FROM MyTable
WHERE (NOW() < date + 10)
ORDER BY new_delay DESC;
DB example:
CREATE TABLE IF NOT EXISTS `MyTable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
INSERT INTO `MyTable` (`id`, `date`) VALUES
(1, (NOW())),
(2, (NOW()-10)),
(3, (NOW()+100));
Any ideas??
Don't do the comparisons like that. In a numeric context now() end up being converted to an integer -- and in an arcane format. Instead, use DATEDIFF() or just regular comparisons. For instance, if you want the difference in days:
SELECT datediff(curdate(), date) as new_delay, id
FROM MyTable
WHERE date >= date_sub(now(), interval 10 day)
ORDER BY new_delay DESC;
use mysql DATEDIFF
select DATEDIFF(curdate(),date) as new_delay, id from MyTable
where date >= date_sub(curdate(), interval 10 day)
ORDER BY new_delay DESC;
DATEDIFF() function returns the time between two dates
As proposed by #Gordon in the his answer, I can use the date_sub / date_add functions...
I can correct the where clause to be :
WHERE NOW() < date_add(ServerRequests.date, interval 10 second)
OR
WHERE date > date_sub(now(), interval 10 second)
OR as proposed in my initial post:
WHERE (NOW() < date + 10)
But I still don't see why I cannot use the sub operation...So if anyone can give me a reason, I would be happy to understand...
In a SQL statement, how do I compare a date saved as TIMESTAMP with a date in YYYY-MM-DD format?
Ex.: SELECT * FROM table WHERE timestamp = '2012-05-25'
I want this query returns all rows having timestamp in the specified day, but it returns only rows having midnight timestamp.
thanks
You can use the DATE() function to extract the date portion of the timestamp:
SELECT * FROM table
WHERE DATE(timestamp) = '2012-05-25'
Though, if you have an index on the timestamp column, this would be faster because it could utilize an index on the timestamp column if you have one:
SELECT * FROM table
WHERE timestamp BETWEEN '2012-05-25 00:00:00' AND '2012-05-25 23:59:59'
As suggested by some, by using DATE(timestamp) you are applying manipulation to the column and therefore you cannot rely on the index ordering.
However, using BETWEEN would only be reliable if you include the milliseconds. In the example timestamp BETWEEN '2012-05-05 00:00:00' AND '2012-05-05 23:59:59' you exclude records with a timestamp between 2012-05-05 23:59:59.001 and 2012-05-05 23:59:59.999. However, even this method has some problems, because of the datatypes precision. Occasionally 999 milliseconds is rounded up.
The best thing to do is:
SELECT * FROM table
WHERE date>='2012-05-05' AND date<'2012-05-06'
WHERE cast(timestamp as date) = '2012-05-05'
SELECT * FROM table WHERE timestamp >= '2012-05-05 00:00:00'
AND timestamp <= '2012-05-05 23:59:59'
Use a conversion function of MYSQL :
SELECT * FROM table WHERE DATE(timestamp) = '2012-05-05'
This should work
As I was researching this I thought it would be nice to modify the BETWEEN solution to show an example for a particular non-static/string date, but rather a variable date, or today's such as CURRENT_DATE(). This WILL use the index on the log_timestamp column.
SELECT *
FROM some_table
WHERE
log_timestamp
BETWEEN
timestamp(CURRENT_DATE())
AND # Adds 23.9999999 HRS of seconds to the current date
timestamp(DATE_ADD(CURRENT_DATE(), INTERVAL '86399.999999' SECOND_MICROSECOND));
I did the seconds/microseconds to avoid the 12AM case on the next day. However, you could also do `INTERVAL '1 DAY' via comparison operators for a more reader-friendly non-BETWEEN approach:
SELECT *
FROM some_table
WHERE
log_timestamp >= timestamp(CURRENT_DATE()) AND
log_timestamp < timestamp(DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY));
Both of these approaches will use the index and should perform MUCH faster. Both seem to be equally as fast.
SELECT * FROM table WHERE DATE(timestamp) = '2012-05-25'
It will work but not used index on "timestamp" column if you have any because of DATE function. below query used index and give better performance
SELECT * FROM table WHERE timestamp >= '2012-05-05 00:00:00'
AND timestamp <= '2012-05-05 23:59:59'
OR
SELECT * FROM table
WHERE timestamp >= '2012-05-05' AND timestamp < '2012-05-06'
Try running these to check stats
explain SELECT * FROM table
WHERE DATE(timestamp) = '2012-05-25'
explain SELECT * FROM table WHERE timestamp >= '2012-05-05 00:00:00'
AND timestamp <= '2012-05-05 23:59:59'
In case you are using SQL parameters to run the query then this would be helpful
SELECT * FROM table WHERE timestamp between concat(date(?), ' ', '00:00:00') and concat(date(?), ' ', '23:59:59')
When I read your question, I thought your were on Oracle DB until I saw the tag 'MySQL'. Anyway, for people working with Oracle here is the way:
SELECT *
FROM table
where timestamp = to_timestamp('21.08.2017 09:31:57', 'dd-mm-yyyy hh24:mi:ss');
Use
SELECT * FROM table WHERE DATE(2012-05-05 00:00:00) = '2012-05-05'
Let me leave here it may help someone
For people coming from nodejs and expressjs
getDailyIssueOperations(dateName, date, status) {
const queryText = `
select count(*) as total from issues
where date(${dateName})='${date}' and status='${status}';
`;
},
in case date and column name are variables please find the implementation usefull
What's the best way to do following:
SELECT * FROM users WHERE created >= today;
Note: created is a datetime field.
SELECT * FROM users WHERE created >= CURDATE();
But I think you mean created < today
You can compare datetime with date, for example: SELECT NOW() < CURDATE() gives 0, SELECT NOW() = CURDATE() gives 1.
SELECT * FROM myTable WHERE DATE(myDate) = DATE(NOW())
Read more:
http://www.tomjepson.co.uk/tutorials/36/mysql-select-where-date-today.html
SELECT * FROM users WHERE created >= NOW();
if the column is datetime type.
Answer marked is misleading. The question stated is DateTime, but stated what was needed was just CURDATE().
The shortest and correct answer to this is:
SELECT * FROM users WHERE created >= CURRENT_TIMESTAMP;
If 'created' is datetime type
SELECT * FROM users WHERE created < DATE_ADD(CURDATE(), INTERVAL 1 DAY);
CURDATE() means also '2013-05-09 00:00:00'
If the column have index and a function is applied on the column then index doesn't work and full table scan occurs, causing really slow query.
Bad Query; This would ignore index on the column date_time
select * from users
where Date(date_time) > '2010-10-10'
To utilize index on column created of type datetime comparing with today/current date, the following method can be used.
Solution for OP:
select * from users
where created > CONCAT(CURDATE(), ' 23:59:59')
Sample to get data for today:
select * from users
where
created >= CONCAT(CURDATE(), ' 00:00:00') AND
created <= CONCAT(CURDATE(), ' 23:59:59')
Or use BETWEEN for short
select * from users
where created BETWEEN
CONCAT(CURDATE(), ' 00:00:00') AND CONCAT(CURDATE(), ' 23:59:59')
Tip:
If you have to do a lot of calculation or queries on dates as well as time, then it's very useful to save date and time in separate columns. (Divide & Conquer)
SELECT * FROM users WHERE created >= now()
The below code worked for me.
declare #Today date
Set #Today=getdate() --date will equal today
Select *
FROM table_name
WHERE created <= #Today
SELECT * FROM table_name WHERE CONCAT( SUBSTRING(json_date, 11, 4 ) , '-', SUBSTRING( json_date, 7, 2 ) , '-', SUBSTRING(json_date, 3, 2 ) ) >= NOW();
json_date ["05/11/2011"]
you can return all rows and than use php datediff function inside an if statement, although that will put extra load on the server.
if(dateDiff(date("Y/m/d"), $row['date']) <=0 ){
}else{
echo " info here";
}