Mysql Date manipulation - mysql

I have a table with different dates and one of them is separated in 3 fields:
PassDay, PassMonth, PassYear.
I want to compare these dates with an other datetime orig_date so what I did is
select `orig_date`, CONCAT_WS('-',`PassYear`,`PassMonth`,`PassDay`) as `pass_expiration` where `pass_expiration` < `orig_date`;
The problem is that the month is stored as a month name (January) and not a number (01), so my result for pass_expiration is 2013-April-15 for example.
Is there a way to transform this (2013-April-15) to a regular datetime directly from the query?

You want str_to_date:
where STR_TO_DATE(CONCAT_WS('-',PassYear,PassMonth,PassDay),'%Y-%M-%d') < orig_date
Also, as a note, you can't reference a computed column in the where clause. Only in the order by clause (where is a predicate that's used to filter results from the table; order by is run after the column set is calc'd).

Related

ORDER BY STR_TO_DATE() not working in phpmyadmin sql

I have dates in varchar type like:
201601
201602
201603
201701
201702 and so on
I am trying to view all my records where the dates are in ascending order. So I am using this query:
SELECT * FROM emp_pp GROUP BY YEARMM ORDER BY STR_TO_DATE(YEARMM,'%Y%m')
Here YEARMM is my column name. The query isn't working properly when I run it. Instead I keep getting all these notices:
Incorrect datetime value: '201601' for function str_to_date
Incorrect datetime value: '201602' for function str_to_date...
Why is that? Please help me
As mentioned by Akina, STR_TO_DATE function requires enough data to generate at minimum a full date value to work correctly. You do not have that (you can not have a date 2016-02-00, for example).
What you do have is a numerical Year and Month integer, 201601, 201602, 201603, 201701 etc. which orders exactly as you want by standard numerical ordering so all you need to do is remove the STR_TO_DATE part entirely:
SELECT * FROM emp_pp GROUP BY YEARMM ORDER BY YEARMM ASC /* Oldest date first */
Of note:
SELECT * is highly inefficient. You should name each column you want to collect.
Column names in SQL should not be upper case, as this is hard to read with the correct case syntax, SQL column should be only lower case; yearmm would be more readable in your SQL code.

Mysql selecting unique values in date type varchar

I have a column where the dates are type varchar. For example:
15-10-2018
16-10-2018
19-10-2018
23-10-2018
29-10-2018
8-11-2018
9-11-2018
10-11-2018
12-11-2018
when I consult with the following query
SELECT DISTINCT date FROM `test` WHERE date BETWEEN '15-10-2018' and '9-11-2018'.
I have the right result.
15-10-2018
16-10-2018
19-10-2018
23-10-2018
29-10-2018
8-11-2018
9-11-2018
but if the query is:
SELECT DISTINCT date FROM `test` WHERE date BETWEEN '15-10-2018' and '10-11-2018'.
or
SELECT DISTINCT date FROM `test` WHERE date BETWEEN '15-10-2018' and '12-11-2018'.
The answer I get is empty.
I think it's only validating the days in the sql.
I need to get the right dates.
I think the problem is the fact that the column is varchar, so it's comparing characters instead of a range of dates. I will recommend convert the column to date type and try again.
Alternative if you cannot change the type of the column you could cast it to date format like this:
SELECT DISTINCT `date` FROM `test` WHERE STR_TO_DATE(`date`,'%d-%m-%Y') BETWEEN '2018-10-15' AND '2018-11-10';
I tested with your data and it works. Of course this could put some extra effort on the database and will not use indexes.
You need to set the datatype to date and update your dates to be using date for a more reliable result. Once done you should be using the database format for the dates in your WHERE clause.
Try
SELECT DISTINCT date FROMtestWHERE date BETWEEN '2018-10-15' and '2018-11-10'

sql error using between operator with date between two dates

i have an events table having start date and end date I am trying retrieve all the records by giving a date that is between start and end dates.
eg :
SELECT *
FROM `events`
WHERE '2017-01-29' BETWEEN start_date='2017-01-28'
AND end_date='2017-01-31'
but response is syntax error can any one help me to finish the query
Just list the columns.
WHERE '2017-01-29' BETWEEN start_date AND end_date
The values come from the table, you don't put them into the query.
According to mysql documentation (https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between) the syntax for BETWEN is
expr BETWEEN min AND max
it is not
expr BETWEEN blabla=min AND stuff=max
Also, it is rather pointless to be using constants in all three expressions, because in this case the result will be known in advance (either always TRUE or always FALSE) without having to consult the values in your table.
It is kind of hard to give you an example without knowing the structure of your table, but what you probably want is something like
WHERE '2017-01-29' BETWEEN start_date
AND end_date
(assuming start_date and end_date are columns in your table)
or something like
WHERE some_column BETWEEN '2017-01-28'
AND '2017-01-31'
(assuming some_column is a column in your table.)
I believe you're trying to find all the rows where a date is 2017-01-29, and so, your query could be:
SELECT *
FROM `events`
WHERE
date = '2017-01-29';
If, however, you want all rows with date between 2017-01-28 and 2017-01-31, then you could do:
SELECT *
FROM `events`
WHERE
date BETWEEN '2017-01-28' AND '2017-01-31';
Instead of putting 2017-01-29 before WHERE, put the name of the field you want to filter by date, such as EventDate (or whatever your field is named).

Date between query in mysql not generated correct output

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 )

SQL Server: Want to use between clause with dates, but dates in string form (YYYY.MM.DD)

Help! One column in my database is for dates. All of my dates are unfortunately in the String form (YYYY.MM.DD). I have a MASSIVE database (300+GB) so ideally would like to avoid transformations.
Is there a way I can select rows for dates in between YYYY.MM.DD and YYYY.MM.DD? What would the script look like?
Thank you!
If the months and days are stored with leading zeroes, the BETWEEN operator will work as expected. So will ORDER BY.
create table your_table (
date_value varchar(10) not null
);
insert into your_table values
('2013.01.01'), ('2013.01.13'), ('2013.01.30'), ('2013.01.31'),
('2013.02.01'), ('2013.02.13'), ('2013.02.28'), ('2013.02.31'),
('2013.03.01'), ('2013.03.15'), ('2013.03.30'), ('2013.03.31');
select date_value
from your_table
where date_value between '2013.01.01' and '2013-01-31'
order by date_value;
2013.01.01
2013.01.13
2013.01.30
One of the main problems with your structure is that you lose type safety. Look at this query.
select date_value
from your_table
where date_value between '2013.02.01' and '2013.02.31'
order by date_value;
2013.02.01
2013.02.13
2013.02.28
2013.02.31
If you'd used a column of type date or datetime or timestamp, the dbms would not have allowed inserting the values '2013.02.31', because that's not a value in the domain of date. It is a value in the domain of varchar. (And so is "Arrrrgh!", unless you've got a CHECK constraint on that column that severely restricts the acceptable values.)
Not good solution, but works (cost much performance).
You have formated date in order year, month, day (good order to compare strings, without transformation to datetime), so you can try
SELECT * FROM Table WHERE StringDate > '2013.07.10' AND StringDate < '2013.07.14'
It returns bad results if there are dates before year 1000 without leading zero ('999.07.14').
But I dont know how it works on big database.
SQL Fiddle
Between in SQL is inclusive of both bounds. If that is what you want, you can just use between:
where col between 'YYYY.MM.DD' and 'YYYY.MM.DD'
Where the two constants are whatever values you are looking for.
If you have an index on the column, then between (as well as >, >=, and so on) will use the index. You do not need to transform the values. If your constants are dates of one form or another, then you can use date_format() to create a string in the right format. For instance, to get dates within the past week:
where col >= date_format(adddate(now(), -7), '%Y.%m.%d')