What's the difference between a TimeStamp field and mysql curdate - mysql

I was working and my friend told me to use curdate() on mysql query to get the current date of the server... And I told him that I was using Time_Stamp field for date/time.
Now I start to think, is there a huge difference between this two ways ? One is better than the other? Or there is something that makes it a not good practice ? Also there is a now() that can be used too. I just wanted to understand how does it work or wich one is the best and why.

Short version:
NOW() = CONCAT(CURDATE(), ' ', CURTIME());
CURDATE() = DATE(NOW());
Some explanation:
NOW() gets both date (CURDATE()) and time (CURTIME()).
So if we do it the other way round, CURDATE() = DATE(NOW()).
Regarding timestamp, in MySQL Data Types we can see timestampis 3 bytes, while datetime is 8 bytes.

Related

Time difference between CURRENT_TIMESTAMP(), CURRENT_DATE() + 0 and CURRENT_DATE()

When I perform this query:
SELECT CURRENT_TIMESTAMP(),CURRENT_DATE()+0,CURRENT_DATE;
I get this result:
CURRENT_TIMESTAMP(), CURRENT_DATE()+0, CURRENT_DATE
2019-03-25 08:54:33, 20190325 , 2019-03-24
Why is the difference between CURRENT_DATE and CURRENT_DATE + 0?
My server version is: 15.1 Distrib 10.1.37-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
Thank you for any suggestion :)
I agree that the result can be somewhat surprising. You add zero to a date and expect it to stay this date. This, however, would imply that you add zero "something", e.g. zero hours or zero days (otherwise: would would +1 mean to a date?).
There are DBMS that do exactly this. In Oracle for example somedate + 1 means somedate + interval '1' day. MySQL, however, doesn't. MySQL rather adds the number (zero in your case) to the internal numeric representation of the date. Why they are doing this, is beyond me. Why would we want to see what MySQL uses internally to store a date? It shouldn't matter to us. So what MySQL does is convert CURRENT_DATE to a numeric value and then add zero, which is why you see a number in your result.
What you can learn from this: Don't add a number to a date, as it has no meaning really. What is October 3, 2008 plus 23 (opposed to "plus 23 days" or "plus 23 weeks" or whatever)? It just has no meaning. So treat this like a flaw in the DBMS to even allow this and just never use it.
You can of course always add an interval to a date, e.g.
select current_date + interval 0 day;
If you want to add some number of days to a MySQL date, then you should use INTERVAL, e.g.
CURRENT_DATE() + INTERVAL 0 DAY
But, since you actually an integer to a MySQL date, here is an explanation. CURRENT_DATE() is a date, while CURRENT_DATE() + 0 ends being a number. Your current query:
SELECT CURRENT_DATE() + 0;
is actually being evaluated as this:
SELECT (CAST CURRENT_DATE() AS UNSIGNED) + 0;
The cast to integer is necessary because you are adding zero, an integer, to the result of CURRENT_DATE().
Convince yourself of this by running:
SELECT (CAST CURRENT_DATE() AS UNSIGNED);
This will return 20180325 as a result.
I think I found the answer - the problem lies in dataGrip desktop client I am using. I am not sure what exactly happens to data, but it seems, that a) dataGrip somehow makes the connection with incorrect timezone or b) incorrectly converts data when receiving. And before you asked, I tried the same query via terminal, MySQL workbench and on the MySQL server itself and I get the correct answer. :)

Select query for two weeks ago

In my database table I have a field for date (varchar field to save date in yy-mm-dd format ), now I want to select records for two weeks ago.
How can i do it ?
Implicit date arithmetic is fairly flexible in MySQL. You can compare dates as strings without explicit use of CAST() or DATE(), but you're trusting MySQL to interpret your format correctly. Luckily for you, it will do just fine with yy-mm-dd.
I would recommend using BETWEEN and INTERVAL so that your query is easily readable; for example:
SELECT * FROM Holidays
WHERE Date BETWEEN (NOW() - INTERVAL 14 DAY) AND NOW();
The only trick with BETWEEN is that you have to put the lower bound first and the upper bound second; for example, if you write BETWEEN 5 AND 2, this always evaluates to FALSE because there is no value that can be greater than or equal to 5 while also being less than or equal to 2.
Here's a demo of the query in action at SQL Fiddle, and a list of the recognized INTERVAL expressions in MySQL.
Note that the parentheses around the expression NOW() - INTERVAL 14 DAY are not required but I would recommend using them here purely for the sake of clarity. It makes the predicate clause just a little bit easier to read in the absence of proper syntax highlighting, at the expense of two characters.
Ideally you should be using date types to store dates, but being that's not the case, you should look into casting to date then comparing.
select * from yourtable where cast (yourdate as Date) BETWEEN Date_Add(CURDATE(), INTERVAL -21 Day) and Date_Add(CURDATE(), INTERVAL -14 Day)
Note, this is untested and may need a little tweaking, but should give you a general idea of what you need to do.
Also, if it's possible, you should really look into converting the varchar field to a date field....they have date types to prevent this sort of thing from happening, although i know changing field types isn't always a possibility.
you can simply do with ADDDATE to get 14 days ago. compare string with date will work.
SELECT *
FROM your_table
WHERE your_date >= ADDDATE(NOW(), -14) AND your_date < NOW()
I use this for select data in past of past
SELECT * FROM Holidays
WHERE a.dDate >= DATE( NOW( ) ) - INTERVAL 14
DAY AND a.dDate <= DATE( NOW( ) ) - INTERVAL 8

MySQL select rows that are exactly 7 days old FROM TIMESTAMP

first of all, I know that my question is very similar to that one:
MySQL select rows from exactly 7 days ago
the difference is that my dates are stored in the database as a timestamp.
I know that I can use FROM_UNIXTIME to get the date from the timestamp, the thing is, in another answer I read that was very resource consuming (because the timestamp field has to be converted to date in all the records before comparing).
DATE(from_unixtime(timestamp)) = CURRENT_DATE()
Is there any optimized way to do this?
Turn it around: calculate the unix timestamp of the target date first and use that.
WHERE timestamp = UNIX_TIMESTAMP(NOW() - INTERVAL 7 DAY)
MySQL should calculate that value once and use it all the time (needs testing though). If it doesn't, use a variable or code.

MySQL Select rows <= now(), using separated time fields

I have a table 't' with date(yyyy-mm-dd), hour(1-12), minute(00-59), ampm(a/p), and timezone(pst/est) fields.
How can I select the rows that are <= now()? (ie. already happened)
Thank you for your suggestions!
edit: this does it without attention to the hour/minute/ap/tz fields:
SELECT * FROM t.date WHERE date <= now()
Here's one way to do it - combine all your seconds, minutes, etc into a date and compare to NOW(), making sure you do the comparison in the same time-zone. (Untested):
SELECT *
FROM t
LEFT JOIN y ON t.constant=y.constant
WHERE CONVERT_TZ(STR_TO_DATE(CONCAT(date,' ',hour,':',minute,' 'ampm),
'%Y-%m-%d %l:%i %p' ),
timezone,"SYSTEM") < NOW();
If your hour is 01 - 12 not 1-12 then use %h instead of %l in the STR_TO_DATE.
The STR_TO_DATE tries to stick your date and time columns together and convert them into a date.
The CONVERT_TZ(...,timezone,"SYSTEM") converts this date from whatever timezone is specified in the timezone column to system time.
This is then compared to NOW(), which is always in system time.
As an aside, perhaps you should make a single column date using MySQL's date datatype, as it's a lot easier to do arithmetic on that!
For reference, here is a summary of very useful mysql date functions where you can read up on those featuring in this answer.
Good luck!
SELECT * FROM t
WHERE `date`<=DATE_SUB(curdate(), INTERVAL 1 DAY)
OR (
`date`<=DATE_ADD(curdate(), INTERVAL 1 DAY)
AND
CONVERT_TZ(CAST(CONCAT(`date`,' ',IF(`hour`=12 AND ampm='a',0,if(ampm='a',`hour`,`hour`+12)),':',`minute`,':00') AS DATETIME),'GMT',`timezone`)<=NOW()
)
Rationale for date<=DATE_[ADD|SUB](curdate(), INTERVAL 1 DAY):
The fancy conversion is quite an expensive operation, so we don't want it to run on the complete table. This is why we pre-select against an UNCHANGED date field (possibly using an index). In no timezone can an event being more than a day in current timezone's past be in the future, and in no timezone can an event more than a day in the curent timezone's future be in the past.

MySQL: Curdate() vs Now()

What is difference between MySQL Curdate() and Now()?
For questions like this, it is always worth taking a look in the manual first. Date and time functions in the mySQL manual
CURDATE() returns the DATE part of the current time. Manual on CURDATE()
NOW() returns the date and time portions as a timestamp in various formats, depending on how it was requested. Manual on NOW().
Just for the fun of it:
CURDATE() = DATE(NOW())
Or
NOW() = CONCAT(CURDATE(), ' ', CURTIME())
CURDATE() will give current date while NOW() will give full date time.
Run the queries, and you will find out whats the difference between them.
SELECT NOW(); -- You will get 2010-12-09 17:10:18
SELECT CURDATE(); -- You will get 2010-12-09
Actually MySQL provide a lot of easy to use function in daily life without more effort from user side-
NOW() it produce date and time both in current scenario whereas
CURDATE() produce date only, CURTIME() display time only, we can use one of them according to our need with CAST or merge other calculation it, MySQL rich in these type of function.
NOTE:- You can see the difference using query select NOW() as NOWDATETIME, CURDATE() as NOWDATE, CURTIME() as NOWTIME ;