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 |
+---------------+
Related
LEFT or DATE_FORMAT, which is faster to re-format date in SELECT query in mysql?
I'll show an example of this problem.
Info of PERSON table
Column name
Type
NAME
VARCHAR(20)
YEAR
DATETIME
PERSON
NAME
YEAR
Travis
2020-01-01
Sam
2021-01-01
If execute 'SELECT YEAR FROM PERSON' query, can see below result.
YEAR
2020-01-01 00:00:00
2021-01-01 00:00:00
But I want result like below.
YEAR
2020-01-01
2021-01-01
So, I wanted use one of below queries.
SELECT LEFT(YEAR,10) FROM PERSON
SELECT DATE_FORMAT(YEAR, '%Y-%m-%d')
However, I wonder what query perform better.
Please, help me..
Technically, LEFT() is nearly four times faster, based on this test on my M1 Macbook. Your result might vary.
mysql> select benchmark(100000000, left(year, 10)) from person;
+--------------------------------------+
| benchmark(100000000, left(year, 10)) |
+--------------------------------------+
| 0 |
+--------------------------------------+
1 row in set (1.75 sec)
mysql> select benchmark(100000000, date_format(year, '%Y-%m-%d')) from person;
+-----------------------------------------------------+
| benchmark(100000000, date_format(year, '%Y-%m-%d')) |
+-----------------------------------------------------+
| 0 |
+-----------------------------------------------------+
1 row in set (6.81 sec)
But given that I had to execute both expressions 100 million times to observe a significant difference, both of them are so fast that I wouldn't worry about it. It's likely that other parts of the query will be of far greater influence on performance.
Worrying about which of these two functions has better performance is like worrying if it's better to use one finger or two fingers to lift a 100kg barbell.
There are two columns (t0 and t1) whose types are timestamp (t0 = 2021-11-18 20:25:09 and t1 = 2021-11-18 20:36:41)
I want to find t1 - t0 (expecting ~11 minutes or ~ 700seconds), but the result is 1132.
I was wondering how - is done between two timestamps and what the unit is.
Use the TIMESTAMPDIFF function for that purpose
For your question:
mysql converts the string into a number and then subtracts, its deterministic but not the result you want
SELECT TIMESTAMPDIFF(MINUTE, '2021-11-18 20:25:09','2021-11-18 20:36:41')
| TIMESTAMPDIFF(MINUTE, '2021-11-18 20:25:09','2021-11-18 20:36:41') |
| -----------------------------------------------------------------: |
| 11 |
SELECT TIMESTAMPDIFF(SECOND, '2021-11-18 20:25:09','2021-11-18 20:36:41')
| TIMESTAMPDIFF(SECOND, '2021-11-18 20:25:09','2021-11-18 20:36:41') |
| -----------------------------------------------------------------: |
| 692 |
db<>fiddle here
> SELECT TIMEDIFF(t1, t2) FROM t;
+------------------+
| TIMEDIFF(t1, t2) |
+------------------+
| -00:11:32 |
+------------------+
1 row in set (0.000 sec)
Please see the example here
- does nothing useful for timestamps, except that the sign of the result will tell you which is greater (assuming month and day are not 0), which is easier tested with a comparison operator.
In general, if you cast a timestamp to a number, you get a number formed by putting the parts of the timestamp together. For instance:
select timestamp('2021-11-18 20:25:09.012345')+0
gives
20211118202509.012345
- effectively casts both operands to a number. So differences in days become differences in millions, differences in months become differences in hundreds of millions, and differences in years become differences in tens of billions. This doesn't provide any useful measure of the difference between two timestamps.
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?
I am trying to convert a TIMESTAMP to the DATETIME, DATE and TIME MySQL types using the FROM_UNIXTIME field. I noticed that the values for TIME and DATETIME fields have different time information on them.
Instead of the insert statement to the table, I am replacing it with a simple select statement that prints the values:
select FROM_UNIXTIME('1468561341') as timestamp_datetime,FROM_UNIXTIME('1468561341','%d/%m/%y') as timestamp_date, FROM_UNIXTIME('1468561341','%h:%m:%s %p') as timestamp_time
The results look like this:
timestamp_datetime: 2016-07-15 05:42:21.000000
timestamp_date 15/07/16
timestamp_time 05:07:21 AM
How can I get consistent time value in both these columns?
the issue is with letter m
it should be i
mysql> select FROM_UNIXTIME(1468561341) as timestamp_datetime,FROM_UNIXTIME(1468561341,'%d/%m/%y') as timestamp_date, FROM_UNIXTIME(1468561341,'%h:%i:%s %p') as timestamp_time;
+---------------------+----------------+----------------+
| timestamp_datetime | timestamp_date | timestamp_time |
+---------------------+----------------+----------------+
| 2016-07-15 05:42:21 | 15/07/16 | 05:42:21 AM |
+---------------------+----------------+----------------+
1 row in set (0.05 sec)
Your problem is that in your FROM_UNIXTIME you are essentially telling it to do
hours-months-seconds -AM/PM
But you want
hours-minutes-seconds -AM/PM
So change it to
FROM_UNIXTIME(1468561341,'%h:%i:%s %p')
instead.
Reference guide for all the time parameters and usage of time functions in MySQL here: https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
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)