I have a table which contains a datetime column. I wish to return all records of a given day regardless of the time. Or in other words, if my table only contained the following 4 records, then only the 2nd and 3rd would be returned if I limit to 2012-12-25.
2012-12-24 00:00:00
2012-12-25 00:00:00
2012-12-25 06:00:00
2012-12-26 05:00:00
NEVER EVER use a selector like DATE(datecolumns) = '2012-12-24' - it is a performance killer:
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
It is much faster to use
SELECT * FROM tablename
WHERE columname BETWEEN '2012-12-25 00:00:00' AND '2012-12-25 23:59:59'
as this will allow index use without calculation.
EDIT
As pointed out by Used_By_Already, in the time since the inital answer in 2012, there have emerged versions of MySQL, where using '23:59:59' as a day end is no longer safe. An updated version should read
SELECT * FROM tablename
WHERE columname >='2012-12-25 00:00:00'
AND columname <'2012-12-26 00:00:00'
The gist of the answer, i.e. the avoidance of a selector on a calculated expression, of course still stands.
... WHERE date_column >='2012-12-25' AND date_column <'2012-12-26' may potentially work better(if you have an index on date_column) than DATE.
You can use %:
SELECT * FROM datetable WHERE datecol LIKE '2012-12-25%'
SELECT * FROM `table` where Date(col) = 'date'
Similiar to what Eugene Ricks said. If one is using spring data/jpa with Java 8 and above you can use plusDays(long hours) to increase day 25 to 26.
Example:
LocalDateTime lowerDateTime=LocalDateTime.parse("2012-12-25T00:00:00");
LocalDateTime upperDateTime = lowerDateTime.plusDays(1l);
System.out.println("my lowerDate =="+lowerDateTime);
System.out.println("my upperDate=="+upperDateTime);
Related
I have a query function that selects all rows from the previous days. However, I need it to only select the rows with yesterdays date but am unsure how to include just the previous day.
My current query is:
SELECT pdate FROM table 1
WHERE pdate < Date(NOW()) + INTERVAL 1 DAY
I would imagine it would look something like this, which has the advantage of using indexes (if you have them implemented)
SELECT pdate FROM table 1
WHERE pdate >= Date(NOW()) - INTERVAL 1 DAY
AND pdate < Date(NOW())
You can use the DATE_SUB() function to get yesterday's date, and then use a WHERE clause condition to look for just that date, like this:
SELECT *
FROM myTable
WHERE DATE(pDate) = DATE_SUB(pDate, INTERVAL 1 DAY);
Here is a list of MySQL's Date and Time Functions which may help you.
NOTE: This will work, but because you are using a function on the pDate column in the where clause this will not be able to take advantage of any indexes you have (see comments below). Brian Driscoll has given an answer that will work better. I am choosing to leave this answer because while it is less efficient, I believe it is more readable as the where clause is very explicit in what it is checking and is slightly more readable. Whether or not the trade off is worth it here is up to the developer.
I have a database table that has fields as such :
TIME(Datetime) Update_ID
2013-11-25 05:00:14 XC3
2013-11-25 06:00:13 XC4
2013-11-25 06:00:19 XC5
2013-12-25 23:00:14 XC6
2013-12-25 24:00:00 XC7
So assuming i want to find a trend on the updates to know which period of the day has the a particular number of updates, what i initially think of is doing something like this :
SELECT COUNT(TIME) FROM table WHERE TIME between '06:00:00' and '12:00:00'
But this doesn't work because i think since the date is not added with the time, a default value for date is added(some date around 1970). If, i add the beginning and enddate in my query, i am afraid it won't give me the results i need.
Use
WHERE HOUR(TIME)...GROUP BY DAY(TIME)
in case you have more than 1 day
You are correct, the problem is that when you do not specify the date, a default one is added.
You can use the EXTRACT function to extract the time from a date, like this:
SELECT COUNT(*)
FROM mytable
WHERE EXTRACT(HOUR_SECOND from TIME) between 60000 and 120000
Note that the time portion in the condition is specified in a different format - i.e. as numbers, without colons and quotes.
Demo on SqlFiddle.
In my database table I have a field for date (varchar field to save date in yy-mm-dd format ), now I want to select records for two weeks ago.
How can i do it ?
Implicit date arithmetic is fairly flexible in MySQL. You can compare dates as strings without explicit use of CAST() or DATE(), but you're trusting MySQL to interpret your format correctly. Luckily for you, it will do just fine with yy-mm-dd.
I would recommend using BETWEEN and INTERVAL so that your query is easily readable; for example:
SELECT * FROM Holidays
WHERE Date BETWEEN (NOW() - INTERVAL 14 DAY) AND NOW();
The only trick with BETWEEN is that you have to put the lower bound first and the upper bound second; for example, if you write BETWEEN 5 AND 2, this always evaluates to FALSE because there is no value that can be greater than or equal to 5 while also being less than or equal to 2.
Here's a demo of the query in action at SQL Fiddle, and a list of the recognized INTERVAL expressions in MySQL.
Note that the parentheses around the expression NOW() - INTERVAL 14 DAY are not required but I would recommend using them here purely for the sake of clarity. It makes the predicate clause just a little bit easier to read in the absence of proper syntax highlighting, at the expense of two characters.
Ideally you should be using date types to store dates, but being that's not the case, you should look into casting to date then comparing.
select * from yourtable where cast (yourdate as Date) BETWEEN Date_Add(CURDATE(), INTERVAL -21 Day) and Date_Add(CURDATE(), INTERVAL -14 Day)
Note, this is untested and may need a little tweaking, but should give you a general idea of what you need to do.
Also, if it's possible, you should really look into converting the varchar field to a date field....they have date types to prevent this sort of thing from happening, although i know changing field types isn't always a possibility.
you can simply do with ADDDATE to get 14 days ago. compare string with date will work.
SELECT *
FROM your_table
WHERE your_date >= ADDDATE(NOW(), -14) AND your_date < NOW()
I use this for select data in past of past
SELECT * FROM Holidays
WHERE a.dDate >= DATE( NOW( ) ) - INTERVAL 14
DAY AND a.dDate <= DATE( NOW( ) ) - INTERVAL 8
I have a table 't' with date(yyyy-mm-dd), hour(1-12), minute(00-59), ampm(a/p), and timezone(pst/est) fields.
How can I select the rows that are <= now()? (ie. already happened)
Thank you for your suggestions!
edit: this does it without attention to the hour/minute/ap/tz fields:
SELECT * FROM t.date WHERE date <= now()
Here's one way to do it - combine all your seconds, minutes, etc into a date and compare to NOW(), making sure you do the comparison in the same time-zone. (Untested):
SELECT *
FROM t
LEFT JOIN y ON t.constant=y.constant
WHERE CONVERT_TZ(STR_TO_DATE(CONCAT(date,' ',hour,':',minute,' 'ampm),
'%Y-%m-%d %l:%i %p' ),
timezone,"SYSTEM") < NOW();
If your hour is 01 - 12 not 1-12 then use %h instead of %l in the STR_TO_DATE.
The STR_TO_DATE tries to stick your date and time columns together and convert them into a date.
The CONVERT_TZ(...,timezone,"SYSTEM") converts this date from whatever timezone is specified in the timezone column to system time.
This is then compared to NOW(), which is always in system time.
As an aside, perhaps you should make a single column date using MySQL's date datatype, as it's a lot easier to do arithmetic on that!
For reference, here is a summary of very useful mysql date functions where you can read up on those featuring in this answer.
Good luck!
SELECT * FROM t
WHERE `date`<=DATE_SUB(curdate(), INTERVAL 1 DAY)
OR (
`date`<=DATE_ADD(curdate(), INTERVAL 1 DAY)
AND
CONVERT_TZ(CAST(CONCAT(`date`,' ',IF(`hour`=12 AND ampm='a',0,if(ampm='a',`hour`,`hour`+12)),':',`minute`,':00') AS DATETIME),'GMT',`timezone`)<=NOW()
)
Rationale for date<=DATE_[ADD|SUB](curdate(), INTERVAL 1 DAY):
The fancy conversion is quite an expensive operation, so we don't want it to run on the complete table. This is why we pre-select against an UNCHANGED date field (possibly using an index). In no timezone can an event being more than a day in current timezone's past be in the future, and in no timezone can an event more than a day in the curent timezone's future be in the past.
I am trying to select rows that are in between two dates. First, here is my data:
punch_id eid time unixtime punch_type day date doy
135 2 12:53 1314723193 0 4 08/28/2011 241
134 2 12:53 1314723190 3 4 08/31/2011 241
133 2 12:53 1314723187 2 4 08/20/2011 241
132 2 12:52 1314723125 1 4 08/30/2011 241
I have tried these two queries.
SELECT * FROM `punches` WHERE `date` >= '08/20/11' AND `date` <= '08/31/11'
SELECT * FROM `punches` WHERE `date` BETWEEN '08/20/11' AND '08/31/11'
Neither of these select the rows containing the date 08/31/11. It selects the 08/20/11 ones though. I tried to use it another way and when I run the query:
SELECT * FROM `punches` WHERE `date` >= '08/10/11' AND `date` <= '08/20/11'
I again do not get the correct result: the 20th is left out once again. What is the problem with the way I am executing this?
See this related question.
As others have mentioned, your primary problem is not accounting for the time. A few options to handle that:
Use a function to convert the DateTime to a Date. I don't recommend this option, since it will likely make the function non-sargeable.
Expand your BETWEEN to explicitly include the last moment of the day: (note: this is the latest possible value that MS SQL can store, don't know if MySQL has the same value)
SELECT * FROM `punches` WHERE `date`
BETWEEN '08/20/11 00:00:00.000' AND '08/31/11 23:59:59.997'
Use a < for the upper value
SELECT * FROM `punches` WHERE `date` >= '08/20/11' AND `date` < '09/01/11'
I actually think that last one is easier, in most situations.
I suppose you could do other things, like change the datatype of the column, but I've assumed here that you're just interested in changing the query.
** Disclaimer: I'm a MS SQL guy, not MySQL
I don't know mysql, but in other RDBMS, dates are assuming a time part of 12 AM. If you want to include the high date, add 1 to the day.
Is your date field of type DATE or DATETIME?
It probably has to do with the time of day. If you have a DATETIME stored as
2011-08-31 13:00:00
then it won't match on
BETWEEN '08/20/11' AND '08/31/11'
You'd have to use
BETWEEN '08/20/11' AND '09/01/11'
The MySQL docs for between say it matches "less than or equal to" max, so it is probably the time of day throwing you off.
When you don't specify a time with the date, then 00:00:00 is implied. Therefore the real query that the database is doing is more like...
SELECT * FROM `punches` WHERE `date` BETWEEN '08/20/11 00:00:00' AND '08/31/11 00:00:00'
Therefore a punch on 08/31/2011 at 12:53 will not get included. I think this should work, and is a bit more elegant than adding a day to the end date...
SELECT * FROM `punches` WHERE DATE(`date`) BETWEEN '2011-08-20' AND '2011-08-31'