I need to get all records those equal and less than 2012-12-28 i used bellow query for this,
booking_time is DATETIME field, and there are records less than 2012-12-28 but it returns zero rows.
does anyone has idea ?
SELECT * FROM ctx_bookings WHERE DATE(booking_time)<=2012-12-28 ORDER BY id ASC
Table filed
+---------------------+
| booking_time |
+---------------------+
| 2012-12-20 03:10:09 |
| 2012-12-25 02:10:04 |
+---------------------+
Please anybody know why is this happening ?
wrap the value with single quote and surely it will work
SELECT *
FROM ctx_bookings
WHERE DATE(booking_time) <= '2012-12-28'
ORDER BY id ASC
SQLFiddle Demo
As documented under Date and Time Literals:
MySQL recognizes DATE values in these formats:
As a string in either 'YYYY-MM-DD' or 'YY-MM-DD' format. A “relaxed” syntax is permitted: Any punctuation character may be used as the delimiter between date parts. For example, '2012-12-31', '2012/12/31', '2012^12^31', and '2012#12#31' are equivalent.
As a string with no delimiters in either 'YYYYMMDD' or 'YYMMDD' format, provided that the string makes sense as a date. For example, '20070523' and '070523' are interpreted as '2007-05-23', but '071332' is illegal (it has nonsensical month and day parts) and becomes '0000-00-00'.
As a number in either YYYYMMDD or YYMMDD format, provided that the number makes sense as a date. For example, 19830905 and 830905 are interpreted as '1983-09-05'.
As #Barmar commented, your literal expression 2012-12-28 is evaluated as the arithmetic (2012 - 12) - 28, which equals 1,972.
Per #JW.'s answer, you can quote that expression to obtain a valid date literal (of the first form, above). Alternatively:
whilst still quoting the literal, you could use any other punctuation character (or even no character) as the delimiter between date parts:
WHERE DATE(booking_time) <= '2012_12_28'
WHERE DATE(booking_time) <= '20121228'
you could remove the delimiters and leave your literal unquoted:
WHERE DATE(booking_time) <= 20121228
Note also that using a filter criterion like this, which uses a function (in this case, the DATE() function) over a column, requires a full table scan in order to evaluate that function—it therefore will not benefit from any indexes. A more sargable alternative would be to filter more explicitly over the range of column values (i.e. times) that satisfy your criteria:
WHERE booking_time < '2012-12-28' + INTERVAL 1 DAY
This is equivalent because any time that falls strictly prior to the following day will necessarily have occurred on or before the day of interest. It is sargable because the column is compared to a constant expression (the result of the + operation being deterministic), and therefore an index over booking_time can be traversed to immediately find all matching records.
SELECT * FROM ctx_bookings WHERE DATE(booking_time)<='2012-12-28' ORDER BY id ASC
try this mate
Related
I am using DATE() function to calculate the difference between two dates in MySQL
value of SYSDATE() function is following
select SYSDATE();
2020-07-15 12:16:07.0
When I am using date from same month, it is giving correct result
select DATE(SYSDATE())- DATE('2020-07-13');
2
But when I am using date from last month it is giving difference as 86 instead of 16;
select DATE(SYSDATE())- DATE('2020-06-29');
86
Edit:
I am aware that we can use DATEDIFF() but I want to verify why DATE() function is giving results like this since we are already using this in code
MySQL doesn't support subtracting one date from another. The code
SELECT DATE '2020-07-15' - DATE '2020-06-29';
should hence result in an error, but MySQL silently converts this to this instead:
SELECT 20200715 - 20200629;
Seeing that you want to subtract two values, it assumes that you want to work with numbers. Dates are not numbers, but their internal representation yyyymmdd can be represented numerically. So, while CAST(DATE '2020-07-15 ' AS int) fails with a syntax error, as it should, MySQL is not consistent, when it comes to subtraction. It generates the numbers 20200715 and 20200629 and works with these.
I consider this a bug. MySQL should either raise an exception or return an INTERVAL when subtracting one DATE from another.
I have a table with a Date column. It has a row where my_date column's value is 2017-11-24
SELECT * FROM mytable WHERE my_date = '2017-11-24 00:00:00' returns that row.
While SELECT * FROM mytable WHERE my_date = '2017-11-24 00:00:01' does not.
From mysql doc; this page says
If one of the arguments is a TIMESTAMP or DATETIME column and the
other argument is a constant, the constant is converted to a timestamp
before the comparison is performed. This is done to be more
ODBC-friendly. This is not done for the arguments to IN().
If I am interpreting this correctly, in the second query, the constant on right side would be implicitly casted to Date field
The second page for casting says -
Conversion to a DATE value takes fractional seconds into account and
rounds the time part. For example, '1999-12-31 23:59:59.499' becomes
'1999-12-31', whereas '1999-12-31 23:59:59.500' becomes '2000-01-01'.
The example shows 1999-12-31 23:59:59.499 -> 1999-12-31. I understand explicit casting is preferred, but I am wondering why mysql chose to typecast the column value instead of constant or if there's something else happening here.
I don't think you are interpreting the docs correctly. The first page you quote is about comparing a DATETIME or TIMESTAMP to a constant. You are comparing a DATE to a constant, so this logic should apply:
Conversion of DATE values:
Conversion to a DATETIME or TIMESTAMP value adds a time part of '00:00:00' because the DATE value contains no time information.
So it's like comparing '2017-11-24 00:00:00' = '2017-11-24 00:00:01' which sensibly returns false.
Comparing DATEs to DATETIMEs/TIMESTAMPs is similar to comparing an int to a double in that the implicit conversion applies to the less precise value. You would not expect 42 to match 42.1, and likewise you shouldn't expect 2017-11-24 to match 2017-11-24 00:00:01.
how to return exactly rows between two dates with timestamps
this code didn't return all row between 01-04 and 07-05
so what is the problem and why it didn't work correctly
and how to select rows between two date with timestamp when i use date
format like this 01-04-2015
SELECT d_send_items.si_id ,
DATE_FORMAT(FROM_UNIXTIME(d_send_items.si_send_date), '%d-%m-%Y')
FROM d_send_items WHERE
DATE_FORMAT(FROM_UNIXTIME(d_send_items.si_send_date), '%d-%m-%Y') BETWEEN '01-04-2015' AND '07-05-2015'
date_format returns a string, so between is using string comparisons to figure out whether the values are between those two you provide.
So, unless your date format is something like yyyy-mm-dd, between is not going to work as you expect.
For example, the date 08-04-2015 is between the two dates 01-04-2015 and 07-05-2015 but the string 08-04-2015 is not between the two strings 01-04-2015 and 07-05-2015, because the most significant portion 08 is beyond the range which terminates at 07....
So you could use:
where
date_format(from_unixtime(d_send_items.si_send_date), '%Y-%m-%d')
between '2015-04-01' and '2015-05-07'
but per-row functions never scale well in relational databases.
If they're proper timestamp fields, I think you can also bypass the conversion and use something like:
where d_send_items.si_send_date >= '01-04-2015'
and d_send_items.si_send_date < '08-05-2015'
(noting the < day following bit for the second conditional since 08-05-2015 is the same as 08-05-2015 00:00:00) assuming MySQL will recognise those date formats as dd-mm-yyyy.
However, even if it doesn't and you have to use some function to turn those string into timestamp values, this is something that would be done once for the whole query rather than (most likely) for every single row.
I have a table with device data, one of the columns created_ts -> varchar(30)
The problem: this data in this column contains both linux timestamps and varchars for example:
1381148885
and
2012-09-17 22:13:17
How can I query this column for all records with created_ts > 2013-10-01
I'd opt for distinguishing between the string formats (either 'YYYY-MM-DD' or unix timestamp integer) by checking for a dash character.
I'd consider explicitly converting both of those formats to the DATE datatype, using an appropriate conversion. I'd compare the resulting DATE value with the date literal.
Something like this:
WHERE IF(LOCATE('-',t.created_ts,5), -- which format (yyyy-mm-dd or integer)
STR_TO_DATE(t.created_ts,'%Y-%m-%d %T'), -- convert yyyy-mm-dd string to date
FROM_UNIXTIME(t.created_ts) -- convert string as integer to date
) >= '2013-10-01' -- compare to date literal
Another option would be to convert the string column and the date literal to integer values, and do an integer comparison. (Again, two different conversions for the string column, depending on the format.)
NOTE: I included the hh:mm:ss portion in the conversion with the %T.
When no time component is supplied, the time components is assumed to be midnight (zeros) 00:00:00, and that comes into play depending on whether or not we want to consider
'2013-10-01 07:34:55' > '2013-10-01 00:00:00'
OP query has a greater than comparison. I used a greater than or equal to comparison.
This could all be adjusted, depending on the requirements. We want to be aware that if we aren't careful, some values will get "rounded down" to the previous midnight, and then when we do a greater than comparison, what we're really getting is equivalent to >= '2013-10-02'.
My preference is to make it more explicit. It makes it easier for the reader to understand what the query is actually doing.
UPDATE
I had the arguments in the LOCATE function backwards... the string to search for should be the first argument, the string to be searched is second. That's been corrected in the query above.
Something like this:
select * from yourTable
where created_ts > '2013-10-01'
or from_unixtime(created_ts) > '2013-10-01';
The difference between to datetimes is the number of seconds between them. This seems to work only if the datetimes occur in the same hour.
Why is this?
mysql> update events set created_at = "2011-04-13 15:59:59", fulfilled_at ="2011-04-13 16:00:00" where id = 1;
mysql> select fulfilled_at - created_at, timediff(fulfilled_at, created_at) from events where id = 1;
+---------------------------+------------------------------------+
| fulfilled_at - created_at | timediff(fulfilled_at, created_at) |
+---------------------------+------------------------------------+
| 4041.000000 | 00:00:01 |
+---------------------------+------------------------------------+
I know I should be using timediff, but I'm just curious why I'm seeing this or if it's documented somewhere.
MySQL is just converting strings into numbers as best it can, so that it can do the mathematical operation on them. In this case, its just stripping out all of the non numerical colons, dashes and spaces.
Try this:
SELECT (20110413155959 - 20110413160000) AS dates;
Your dates, without all the stuff that stops them being numbers - the result is -4041
Recall that mysql has two differente kinds of datetime-related substractions: The _SUB suffix is for substracting a date minus an interval, returning a date. The _DIFF suffix is for getting the difference between two dates, returning an interval (BTW, notice that only the first one has an inverse analog: _ADD)
The +/- signs are to be used for the first one (ADD/SUB), hence MYSQL expects an interval as a second argument.
DATE = DATE_ADD(DATE,INTERVAL) Also accepts +
DATE = DATE_SUB(DATE,INTERVAL) Also accepts -
INTERVAL = DATE_DIFF(DATE,DATE )
See doc here, the bit starting from:
Date arithmetic also can be performed using INTERVAL
together with the + or - operator...
Hence, it's incorrect to use the - to take the difference between two dates. Now, MYSQL, when confronted with incorrect outputs, tries to do its best guess (instead of throwing an error), sometimes that goes well, sometimes not.