I stored date field as Varchar.
When I use this query :
SELECT date
FROM g_m_tit
WHERE date BETWEEN '01.10.2015' AND '31.10.2015';
it generates the wrong output, as shown below
With VARCHAR column, comparing to strings, that will be a character by character comparison, from left to right.
If you want string comparisons to be used for "date" comparisons, the date values will need to be stored in a consistent and canonical format, with the year first, then the month, then the day. e.g. '2016.01.13'.
MySQL provides datatypes other than VARCHAR specifically for storing date and time values... DATE, DATETIME, TIMESTAMP.
Dealing with date values stored in VARCHAR columns, in the format you have, is going to be some messy SQL. And MySQL is going to have to scan all rows to evaluate the expression; it won't be able to use a range scan operation.
One way to do it is to convert the strings into DATE values, and compare the DATE values.
WHERE STR_TO_DATE(`date` ,'DD.MM.YYYY')
BETWEEN STR_TO_DATE('01.10.2015','DD.MM.YYYY')
AND STR_TO_DATE('31.10.2015','DD.MM.YYYY')
If there are any string values in date that can't be converted to a DATE, because the format doesn't match the specification, or an "invalid" date value, e.g. 32.13.2015, the STR_TO_DATE function will return a NULL or throw an error (depending the SQL_MODE setting).
In your image note how the first 2 characters are between '01' and '31'. The between operator works on varchars using varchar "rules" e.g. '19' IS between '01' and '31' and that is why you are getting unwanted results. You are expecting date rules to be applied but your expectation isn't accurate.
Do not store dates as a string; but if you simply had to do it for some reason only a sequence such as YYYYMMDD allows you to reliably use between.
If you persist in storing the column as varchar with the pattern dd.mm.yyyy then try these:
SELECT
`date`
FROM g_m_tit
WHERE str_to_date(`date`,'%d.%m.%Y') BETWEEN '2015-10-01' AND '2015-10-31';
SELECT
`date`
FROM g_m_tit
WHERE str_to_date(`date`,'%d.%m.%Y') >= '2015-10-01')
AND str_to_date(`date`,'%d.%m.%Y') < '2015-11-01';
both of these, as you can see, force you into changing the data, and you would need to do that every time you reference that "date" column - that is very inefficient.
Also, date is a reserved word, please avoid using such words as column names.
A final note: I prefer the second query above as I never use between for date ranges.
create new column with "date" or "bigint" type
Update all rows inserting value from old column to new (based on new column type)
Delete old column
Rename new one to "g_m_tit"
do not use varchar for dates! It causing probelms as u can see and its slower than date/bigint
To store date in:
"varchar(10)" u need 11 bytes + charset collate every query
"bigint" u need 8 bytes (available range condition)
"date" u need 3 bytes (available range, by part of date conditions and much more )
Related
I am wondering why the following query doesn't yield any result if time is also included in the query?
SELECT * FROM `tb_posts` WHERE DATE(`post_date_published`) = '2013-05-05 16:20:58'
However, when time is excluded from the search parameter
SELECT * FROM `tb_posts` WHERE DATE(`post_date_published`) = '2013-05-05'
Then it fetches the related record from database.
How can we fetch record still using time in the query?
When you compare a DATE with an expression that isn't also DATE, it treats the date as being at time 00:00:00. This is mentioned in the documentation:
When you compare a DATE, TIME, DATETIME, or TIMESTAMP to a constant string with the <, <=, =, >=, >, or BETWEEN operators, MySQL normally converts the string to an internal long integer for faster comparison (and also for a bit more “relaxed” string checking).
So it's comparing the numeric representation of the date with the numeric representation of the datetime string constant, and they don't match because of the different times.
So you need to remove the time from the string:
SELECT * FROM `tb_posts` WHERE DATE(`post_date_published`) = DATE('2013-05-05 16:20:58')
I faced the issue related to min/max functions with a date.
For example - I get Varchar result datatype when querying min(Timestamp(dateColumn)), but I need Timestamp result datatype, I checked these functions with many different functions inside and it returns Varchar always, in every case except when I just call min(dateColumn). In the application I can't cast this operation every time, how could I cope with it?
I have tried to get a date from jdbc ResultSet but I can't track when I have to use result.getTimesatamp. It is impossible to track it.
I expect the min(timestamp('2019-01-01')) or max(timestamp('2019-01-01')) result with Timestamp/Date datatype, but actual result is Varchar result datatype.
Example - SELECT MIN(TIMESTAMP(orders.OrderDate)) FROM orders
The result will be with varchar datatype, but I need the timestamp.
Querying in workbench, dbeaver - results are the same
It is a bug in MySQL. You can do:
select max(x)
from (
select timestamp(now()) as x
) as x;
Or just use:
select min(dateColumn)
as use of the timestamp()-function is unnecessary in the query.
I have a table with a few columns. One of the column is named flight_date is varchar format.
It has a date stored in it in format like '08/12/2015' which is mm/dd/yyyy
I want to run a query which will return me a list of the records with date in 2016.
Can someone help me out please.
Thanks.
In this case, you can use SUBSTR function for just cut last 4 character.
SELECT * FROM yourtable where SUBSTR(flight_date, -4) = '2016'
Though, it is recommended to store date value in appropriate type column and not in varchar.
It sounds simple but I'm stuck. What I want is to be able to compare two MySQL DATETIME values but due to the open ended nature of how the queries are formed I do not know the datatype of value 1 or value 2. For instance, each value can either be a string that is input by an end user, a date field or a DATETIME field.
Example:
dateTime1 > 1/18/2017 2:30pm
The issue I'm running into is STR_TO_DATE() expects a string and returns null with DATETIME, DATE_FORMAT() expects a date and returns null with a string. I need a function or nested group of functions that will give me the same result regardless of the value of the datatype & would like to address directly in mysql rather than pre-processing or making the user input validation stricter. I used to use CAST(value, DATETIME), however CAST() doesn't read the date correctly in the more recent versions of MySQL (it ignores the am/pm specification). Any ideas?
GREATEST() did not work for me as it would always return null if any component was null, however it led me to COALESCE() which provides me with the solution I am looking for as it returns the first non NULL value. It makes the assumption the value will always be DATE, DATETIME, or a date time string which is the case for my issue:
SELECT COALESCE(STR_TO_DATE(value1, '%c/%e/%Y %r'), value1) > COALESCE(STR_TO_DATE(value2, '%c/%e/%Y %r'), value2)
Note: value1 and value2 are either DATE / DATETIME columns or date time string values
You can consider using the coalesce() function, with a list of different formats used with str_to_date(). coalesce() will ignore any null from the list (but at least one of them should be non-null, or you still get a null).
select
coalesce(
str_to_date('13/18/2017 2:30pm', '%m/%e/%Y %l:%i%p') -- will get a null
, str_to_date('18/13/2017 2:30pm', '%e/%m/%Y %l:%i%p') -- will get a null
, str_to_date('18/01/2017 14:30', '%e/%m/%Y %k:%i')
) as answer;
The code may be brittle, because there are so many different date/time formats that a human user may input.
You may also need to be very familiar with all the different format characters that str_to_date() take. See this manual page for more details:
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format
Updated
An earlier version of this answer incorrectly suggested the use of the greatest() function.
I have a mysql column where the data is stored as VARCHAR though the data values are of datetime in the format of yyyy-mm-dd hh:mm:ss.
Now my task is to group by the date part i.e yyyy-mm-dd by converting VARCHAR to date-time and then just taking date part out of it
QUERY
SELECT SUM(value)
FROM table
GROUP BY name , [date part of the varchar field]
Please let me know if this is at all possible and if yes, how?
Assuming that your data in this varchar field is properly formatted, you can work with the left function, like this:
SELECT LEFT(mydate, 10) AS myval,
SUM(myvalue)
FROM mytable
GROUP BY myval;
If this isn't a big issue; I'd advise converting your varchar column to datetime or timestamp. If not only for the possibly better data storage usage, it'll be way easier to do work with date and time related functions.
Just use the left function. You can leave the date as a string:
SELECT left(datecol, 10) as YYYYMMDD, SUM(value)
FROM table
GROUP BY left(datecol, 10);
I removed name from the group by because it doesn't seem relevant to the question. You can, of course, add it back in.
By the way, MySQL understands this format for dates, so if you really, really want a date:
SELECT date(left(datecol, 10)) as RealDate, SUM(value)
FROM table
GROUP BY RealDate;