Find if a date is in date range using MySQL - mysql

Hi I have following values stored in MySQL table:
--- ------------------------ -------------------
Id | StartDate (VARCHAR (20)) | EndDate(VARCHAR(20))
--- ------------------------ -------------------
1 | 03-04-2017 | 18-04-2017
I am using the following SQL to find if the date is within the StartDate and EndDate:
SELECT
(date_format(str_to_date('03-04-2017','%d-%m-%Y'),'%d-%m-%Y') >= StartDate
AND
date_format(str_to_date('03-04-2017','%d-%m-%Y'),'%d-%m-%Y') <= EndDate) AS
valid
FROM holiday
My issue is it that when I execute the query and provide 03-04-2017 it returns 1 but also returns 1 when I provide 03-05-2017.
Could someone please highlight what is wrong in this query?

Use a query like this:
SELECT *
FROM holiday
WHERE
STR_TO_DATE(StartDate,'%d-%m-%Y')
BETWEEN
str_to_date('03-04-2017','%d-%m-%Y')
AND
str_to_date('03-04-2017','%d-%m-%Y');
sample
mysql> SELECT IF(STR_TO_DATE('11-04-2017','%d-%m-%Y')
-> BETWEEN
-> str_to_date('03-04-2017','%d-%m-%Y')
-> AND
-> str_to_date('10-04-2017','%d-%m-%Y')
->
-> ,'YES','NO') AS ANSWER;
+--------+
| ANSWER |
+--------+
| NO |
+--------+
1 row in set (0,00 sec)
mysql> SELECT IF(STR_TO_DATE('04-04-2017','%d-%m-%Y')
-> BETWEEN
-> str_to_date('03-04-2017','%d-%m-%Y')
-> AND
-> str_to_date('10-04-2017','%d-%m-%Y')
->
-> ,'YES','NO') AS ANSWER;
+--------+
| ANSWER |
+--------+
| YES |
+--------+
1 row in set (0,01 sec)
mysql>

You can use BETWEEN operator to compare the dates, e.g.:
SELECT *
FROM `table`
WHERE '2017-04-03' BETWEEN start_date AND end_date;
Update
If the dates are stored as varchar then you need to convert it to date before comparing, e.g.:
SELECT *
FROM table
WHERE '2017-04-03' BETWEEN STR_TO_DATE(start_date, '%d-%m-%Y') AND STR_TO_DATE(end_date, '%d-%m-%Y');
Here's the SQL Fiddle.

All other answers are good for your question but in my opinion you should convert your database.
It's only sane option.
Using dates in weird VARCHAR format will have big impact in future. Not only it impacts perfomances of your tables right now but you are missing whole MySQL date API ecosystem because of it.
Add temporary columns let's say tmp_start_time DATE
Fill them with dates UPDATE holiday SET tmp_start_time = str_to_date(start_time,'%d-%m-%Y')
Drop old varchar keys in table
Add same keys but as DATE
Update them UPDATE holiday SET start_time = tmp_start_time
From now on you would be able to use BETWEEN as everyone else without str_to_date
I just found your comment
unfortunately I cannot change schema
ask yourself twice: are you sure?

Related

Mysql subtraction operator on timestamps [duplicate]

This question already has answers here:
What is the behavior for the minus operator between two datetimes in MySQL?
(2 answers)
Closed 1 year ago.
I wrote a query like
select endtime - begintime ....
and it looked like the difference in seconds. But it turns out that it is very odd number (both columns of type timestamp, no timezones mentioned).
select timestampdiff(seconds, begintime, endtime)
works.
But I am more than a little curious as to what the subtraction operator does! I could not find any documentation. It is certainly a booby trap for new users.
(And nobody really understand timezones. There is what is stored, vs what is displayed in different time zones, which drivers etc. muck with it, and lots and lots of false information and confusion. I don't know what With Timezone really means, but I only use the one timezone of the server, although my browser is in a different timezone so phpadmin might be lying to me.)
When used as a number, a timestamp like '2021-01-02 03:04:05' will be treated as 20210102030405. You can see this with e.g. select timestamp('2021-01-02 03:04:05')-0;. Subtracting two such "numbers" isn't going to be meaningful, except that the sign of the result will tell you which time was later.
This doesn't apply if you use the special INTERVAL syntax to adjust a timestamp by an interval, e.g. select '2021-01-02 03:04:05' - INTERVAL 1 WEEK;.
Here's a demo:
mysql> create table mytable (endtime datetime, begintime datetime);
Query OK, 0 rows affected (0.05 sec)
mysql> insert into mytable values (now(), '2021-05-01');
mysql> select endtime - begintime from mytable;
+---------------------+
| endtime - begintime |
+---------------------+
| 6011403 |
+---------------------+
What's up with this weird value? Well, when you put datetime values into an integer arithmetic expression, they values are converted to integers, but not in units of seconds. You can also force these values to be integers this way:
mysql> select endtime+0 as e, begintime+0 as b from mytable;
+----------------+----------------+
| e | b |
+----------------+----------------+
| 20210507011403 | 20210501000000 |
+----------------+----------------+
Here we see that the values are integers, but they are based on converting the datetime values to YYYYMMDDHHMMSS format.
Guess what the difference is?
mysql> select e-b from (select endtime+0 as e, begintime+0 as b from mytable) as t;
+---------+
| e-b |
+---------+
| 6011403 |
+---------+
But this is not the actual time difference, because there are not 100 minutes in an hour, 100 hours in a day, etc.
mysql> select timestampdiff(second, begintime, endtime) as timestampdiff from mytable;
+---------------+
| timestampdiff |
+---------------+
| 522843 |
+---------------+

Regular expressions on strings in SQL statement

I have a table with following columns and sample data
File Name | Status
'xxx_2015-07-20.csv' | Completed
'xxx_2015-07-19.csv' | Completed
'xxx_2015-07-18.csv' | Failed
.
.
'xxx_2015-06-01.csv' | Failed
Now I have two scenarios in my application (PHP-MySQL):
1) I have to fetch the status of today's file. I can do it like this:
select status from myTable where file_name like '%date(Y-m-d)%';
2) I want to fetch the status of all files generated since 1 month from today. Suppose today is 2015-07-20, then files from 2015-06-20 should show up.
Since there is no date column, I can't apply comparison operator and get the results. I believe it will need some playing with regular expressions.
I am not familiar with regular expressions, so any help on this would be much appreciated.
If the pattern is same i.e. xxx_2015-07-20.csv you can use substring_index function to get the date value as
mysql> select substring_index(substring_index('xxx_2015-07-20.csv','_',-1),'.',1) as d;
+------------+
| d |
+------------+
| 2015-07-20 |
+------------+
Now using the same you can have the select statement as
select status from myTable
where
substring_index(
substring_index(file_name,'_',-1),
'.',1
) = curdate();

Current time in millisecond in MYSQL

How to get the current time in millisecond in MySQL.
So far what I've got is UNIX_TIMESTAMP().
But it returns the current time in seconds.
But I want the current time in milliseconds in UTC since '1970-01-01 00:00:00' in MySQL.
Any suggestion?
Looking at the documentation, it sounds like you want
NOW(3)
... where the value 3 is used to specify that you want 3 digits of subsecond precision, i.e. milliseconds. (Unfortunately none of the examples in the docs show that being used, so it's relatively tricky for me to check this...)
To get that as a "milliseconds since the Unix epoch" value, you'd probably want to use:
UNIX_TIMESTAMP(NOW(3)) * 1000
Thi is my answer;
mysql> Select curtime(4);
+------------+
| curtime(4) |
+------------+
| 13:27:20 |
+------------+
1 row in set (0.00 sec)
Or can also make this:
mysql> select conv(
-> concat(
-> substring(uid,16,3),
-> substring(uid,10,4),
-> substring(uid,1,8))
-> ,16,10)
-> div 10000
-> - (141427 * 24 * 60 * 60 * 1000) as current_mills
-> from (select uuid() uid) as alias;
+---------------+
| current_mills |
+---------------+
| 1427995791797 |
+---------------+
1 row in set (0.00 sec)

How to get Data Between Two Dates in mysql?

Table field structure:
id fdate tdate name
1 2012-07-07 2012-07-30
2 2012-08-07 2012-09-30
3 2012-07-17 2012-08-30
Here
fdate--->one of the field in table
tdate--->another field in table
I Will pass Two values like 2012-07-07 and 2012-09-30
And I need the output From the above Range:
You Have to Check the condition like the following fdate between2012-07-07and2012-09-30and tdate between2012-07-07and2012-09-30 like that
Expected Output:
month Days
07 43
08 53
09 30
Edit: Based on the authors comments the question is - How do I count all the days and show a total grouped by month when passing it a date range and comparing it to the data in my table.
I know that this doesn't give you the exact result that you want, but I think it will help you in the right direction at the very least:
mysql> create table dateTest (id int(2), fdate date, tdate date);
Query OK, 0 rows affected (0.04 sec)
mysql> insert into dateTest values(1, '2012-07-07', '2012-07-30');
Query OK, 1 row affected (0.00 sec)
mysql> insert into dateTest values(1, '2012-08-07', '2012-09-30');
Query OK, 1 row affected (0.00 sec)
mysql> insert into dateTest values(1, '2012-07-17', '2012-08-30');
Query OK, 1 row affected (0.00 sec)
mysql> select month(tdate) as month, datediff(tdate, fdate) as tally from dateTest group by month(fdate), month(tdate);
+-------+-------+
| month | tally |
+-------+-------+
| 7 | 23 |
| 8 | 44 |
| 9 | 54 |
+-------+-------+
3 rows in set (0.00 sec)
As you can see, it is skipping the middle month as I am grouping by fdate, but it is a step in the right direction for you.
Have a look at the TIMESTAMPDIFF() function in MySQL.
What this allows you to do is pass in two TIMESTAMP or DATETIME values (or even DATE as MySQL will auto-convert) as well as the unit of time you want to base your difference on.
You can specify MONTH as the unit in the first parameter:
mysql>SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-04')
-- Outputs: 1
mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
-> -1
mysql> SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55');
-> 128885
Your question is not clear though. But I have this for you.
You need to fetch your data from MySQL table using php. Then you may calculate date difference there.
You may refer to this stackoverflow question How to calculate the difference between two dates using PHP? and the official php documentation about date_diff at http://php.net/manual/en/function.date-diff.php
You can use the between clause in my sql:
select * from tbl where datetime between '2012-07-07' and '2012-09-30';
as an example

mysql 00/00/00 00:00:00 grab and update to a int timestamp in new column

Alright, I have a field which is called timestamp and it is formatted as such:
00/00/00 00:00:00 and I want to grab that field and then updated it in int timestamp form to a field called tm_unix. So how would I do that with a single update? I can do it as a php loop but thought there has to be a way to do it mysql and just need a quick answer.
Unless someone can tell me how to find less than 30 days on the format 00/00/00 00:00:00?
Thanks
Edit: I am using mysql4
UPDATE nameoftable SET tm_unix=UNIX_TIMESTAMP(timestamp)
I don't know the order of day,month and year in 00/00/00 00:00:00
I give you an example
select datediff(curdate(),str_to_date('21/03/11 00:00:00','%d/%m/%Y %T')) -- 32
Put modifier in the right order to match your situation. As you see you can calculate date differences without using unix timestamp. I suggest you to use str_to_date() function with an update query in order to modify your format.
edit. I've added a simple example:
create table example (
id int not null auto_increment primary key,
datestr varchar(20),
unixfield int) engine = myisam;
insert into example (datestr)
values
('01/04/11 15:03:02'),
('22/04/11 19:03:02');
update example
set unixfield = unix_timestamp(str_to_date(datestr,'%d/%m/%Y %T'));
select *,from_unixtime(unixfield) from example;
+----+-------------------+------------+--------------------------+
| id | datestr | unixfield | from_unixtime(unixfield) |
+----+-------------------+------------+--------------------------+
| 1 | 01/04/11 15:03:02 | 1301662982 | 2011-04-01 15:03:02 |
| 2 | 22/04/11 19:03:02 | 1303491782 | 2011-04-22 19:03:02 |
+----+-------------------+------------+--------------------------+
2 rows in set (0.00 sec)
EDIT. SECOND UPDATE.
This is an example of how you can emulate str_to_date() playing with substring() and substring_index() functions.
set #dtstring = '21/03/11 15:23:10';
select str_to_date(#dtstring,'%d/%m/%Y %T'); -- 2011-03-21 15:23:10
select concat('20',substring(#dtstring,7,2),'-',substring(#dtstring,4,2),'-',substring(#dtstring,1,2),' ',substring_index(#dtstring,' ',-1)) -- 2011-03-21 15:23:10
So, my update query will become:
update example
set unixfield = unix_timestamp(concat('20',substring(datestr,7,2),'-',substring(datestr,4,2),'-',substring(datestr,1,2),' ',substring_index(datestr,' ',-1)));