135

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 ?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Jackie Honson
  • 1,419
  • 3
  • 13
  • 12

10 Answers10

234

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

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
John Woo
  • 258,903
  • 69
  • 498
  • 492
  • See the difference: [SQL-Fiddle](http://www.sqlfiddle.com/#!2/1362b/2) Notice the FILTERED = 25 in the 2nd query. – ypercubeᵀᴹ Feb 08 '13 at 12:28
  • @ypercube oh i missed that but i was wondering why is the value on extra `Using where; Using index`? – John Woo Feb 08 '13 at 12:35
  • 1
    The index is used to select the rows. But the whole index is scanned (and all values are converted with DATE() to evaluate the condition) with your query. I'll update my answer with a better example. – ypercubeᵀᴹ Feb 08 '13 at 12:43
  • Check how the index may not be used in your query, if there are many rows (and other columns). – ypercubeᵀᴹ Feb 08 '13 at 13:11
  • 1
    with all due respect, ypercube solution is better for performance reasons, if your table has hundreds of thousands of lines, you should definitely go in this direction – Vincent Dec 28 '14 at 05:36
  • 1
    the `` are important because `timestamp` (and `date` as in my case) is a MySQL reserved word – Victor Ferreira Jan 10 '15 at 19:39
  • The answer by ypercubeᵀᴹ is better than this one -- because of being able to use an index. – Rick James Aug 28 '16 at 19:26
74

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.

ypercubeᵀᴹ
  • 113,259
  • 19
  • 174
  • 235
  • great explanation and thanks for the sql-fiddle. one comment on your schema that threw me for a moment, that `INDEX t_IX (timestamp, id)` could (should?) just be `INDEX t_IX (timestamp)`, as the primary key is implied in the index. or is there a reason i don't understand for doing that? i tried it in sql-fiddle and saw the same (better) execution plan – natbro Nov 05 '13 at 00:55
  • 1
    @natbro Yes, if the table uses the InnoDB engine, the `id` (because it is the PK and thus the clustered index of the table) is appended in the index anyway. So, it doesn't hurt to explicitly add it (and it may catch some optimizer blind spots). It's certainly not relevant in this case/query. – ypercubeᵀᴹ Nov 05 '13 at 12:52
  • Can anyone explain why `timestamp < CURDATE() + INTERVAL 1 DAY` is necessary? – Nightwolf Jan 03 '17 at 13:04
  • @Nightwolf because you may have rows stored where the timestamp value is in the future. The question asks for *"only today's records"*. – ypercubeᵀᴹ Jan 03 '17 at 13:10
  • @TypoCubeᵀᴹ Aha, did not consider that purely because timestamp will not do future dates. Nonetheless good point to keep in mind. – Nightwolf Jan 03 '17 at 13:15
14
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

Hamed Persia
  • 275
  • 3
  • 7
  • 1
    a) The question asks for "only today's records", and your code get also future dates. b) Your comparison don't work, you must do it with DATE(timestamp) In other words: If you fix your answer, you'll obtain @JohnWoo original answer. – Katapofatico Jun 02 '20 at 11:54
  • it is "shorter" to write but **whole world** slower to execute – Your Common Sense Jan 19 '21 at 05:32
4

Or you could use the CURRENT_DATE alternative, with the same result:

SELECT * FROM yourtable WHERE created >= CURRENT_DATE

Examples from database.guide

kochauf
  • 356
  • 3
  • 7
3

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();
ypercubeᵀᴹ
  • 113,259
  • 19
  • 174
  • 235
2

This could be the easiest in my opinion:

SELECT * FROM `table` WHERE `timestamp` like concat(CURDATE(),'%');
Jerry Jones
  • 776
  • 1
  • 13
  • 29
1

Simply cast it to a date:

SELECT * FROM `table` WHERE CAST(`timestamp` TO DATE) == CAST(NOW() TO DATE)
MarcDefiant
  • 6,649
  • 6
  • 29
  • 49
1

How many ways can we skin this cat? Here is yet another variant.

SELECT * FROM table WHERE DATE(FROM_UNIXTIME(timestamp)) = '2015-11-18';

Stephane Gosselin
  • 9,030
  • 5
  • 42
  • 65
0

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)

RedNet
  • 416
  • 5
  • 12
0
SELECT * FROM table WHERE FROM_UNIXTIME(your_column_with_unix_time,'%Y-%m-%d') = CURDATE()
Darksymphony
  • 2,155
  • 30
  • 54