STR_TO_DATE() vs CONSTANT when comparing DATETIME field - mysql

There is a table with DATETIME field named 'created_at'.
I try execute two queries like this:
SELECT * FROM myTable WHERE created_at BETWEEN '2015-03-15 10:25:00' AND '2015-03-25 10:30:00';
SELECT * FROM myTable WHERE created_at BETWEEN
STR_TO_DATE('2015-03-15 10:25:00', '%Y-%m-%d %H:%i:%s') AND STR_TO_DATE('2015-03-25 10:30:00', '%Y-%m-%d %H:%i:%s');
I always used the first query, but recently came across an article in which describes that the second approach is the best way to compare DATETIME. Unfortunately, it does not contain any explain why that approach is the best way.
Now, I have some questions:
Is there any difference between these two approaches?
Which way is more preferable?
Thanks!

I much prefer to put the constants in directly. I believe that MySQL will process the str_to_date() function only once for the query, because the arguments are constants. However, I don't like to depend on this optimization.
The advantage to str_to_date() is that it should be independent of internationalization settings so the result should be unambiguous. However, the use of ISO standard formats should be equivalent, and that is the structure of your constants.
However, that aside, a better way to write the query is:
SELECT *
FROM myTabl
WHERE created_at >= '2015-03-15 10:25:00' AND
created_at < '2015-03-25 10:30:00'
I am guessing that you don't really want 10 days, five minutes and one second in the interval, but want exactly 10 days and five minutes. In any case, the use of between with dates and datetimes can cause unexpected results, particularly when you do:
where datetime between '2015-03-15' and '2015-03-16'
If you think you are getting two dates, you are wrong. You are getting all date times on the first day plus midnight on the second.

Related

incorrect datetime value "2019-06%" - Query works, but with warning

WHERE theDate LIKE '2019-06%'
Is there any "correct" way of running a query like this, or do I have to split up the string first? And in that case, what is the correct way of doing the query if I have the year and month as separate strings. I read that using MONTH and YEAR is not optimal?
The fastest query when you have set indexes properly (faster than LIKE, faster then MONTH, YEAR) will be
WHERE thedate BETWEEN '2019-06-01' AND '2019-06-30'.
I'm not sure if the borders are included or excluded, maybe the borders will be last may and/or first july.

SQL query doesn't work on a specific day

I have a weird problem in mysql!
my query is
SELECT * FROM aa WHERE problemTime>= '2016/03/20' AND problemTime<= '2016/04/20'
the result of this query is nothing , but when I change the first time to 2016/03/19 or 2016/03/21 I have the following result! I mean these queries
SELECT * FROM aa WHERE problemTime>= '2016/03/21' AND problemTime<= '2016/04/20'
or
SELECT * FROM aa WHERE problemTime>= '2016/03/19' AND problemTime<= '2016/04/20'
the result in both time ( 19th and 21th) is
but when I use 20th the result is noting
my main table is
I change the format of time from 2016/03/20 to 2016-03-20 ( I mean change / to - ) but it doesn't have change too!
whats the problem?
You should really be running a query like this if your problemTime column is datetime type:
SELECT * FROM aa
WHERE
problemTime>= str_to_date('2016/03/20', '%Y/%m/%d') AND
problemTime <= str_to_date('2016/04/20', '%Y/%m/%d')
Don't rely on implicit conversions between string and date.. leave your table data alone and ensure you explicitly convert your where clause parameters to the same data type as in the table. Also remember that a date "without" a time is actually midnight on the day in question, and midnight is like zero, it's the first thing that happens on any given day. A time of 6am on a given date, is after midnight, so a query that asks for dates less than or equal to midnight on a particular date means the 6am date will be excluded
This is general good DB practice; do not convert table data where possible, because it can cause huge performance hits and wrong results
Your column "problemTime" have date with time. Do not convert table data, change your where clause (add time).
SELECT * FROM aa WHERE problemTime>= '2016/03/20 00:00:00' AND problemTime<= '2016/04/20 23:59:59'
Try this as per SQl Server.
SELECT * FROM aa
WHERe cast(problemTime AS date) between '2016/03/21' AND '2016/04/20'

why i cant return rows between two dates with timestamp correctly

how to return exactly rows between two dates with timestamps
this code didn't return all row between 01-04 and 07-05
so what is the problem and why it didn't work correctly
and how to select rows between two date with timestamp when i use date
format like this 01-04-2015
SELECT d_send_items.si_id ,
DATE_FORMAT(FROM_UNIXTIME(d_send_items.si_send_date), '%d-%m-%Y')
FROM d_send_items WHERE
DATE_FORMAT(FROM_UNIXTIME(d_send_items.si_send_date), '%d-%m-%Y') BETWEEN '01-04-2015' AND '07-05-2015'
date_format returns a string, so between is using string comparisons to figure out whether the values are between those two you provide.
So, unless your date format is something like yyyy-mm-dd, between is not going to work as you expect.
For example, the date 08-04-2015 is between the two dates 01-04-2015 and 07-05-2015 but the string 08-04-2015 is not between the two strings 01-04-2015 and 07-05-2015, because the most significant portion 08 is beyond the range which terminates at 07....
So you could use:
where
date_format(from_unixtime(d_send_items.si_send_date), '%Y-%m-%d')
between '2015-04-01' and '2015-05-07'
but per-row functions never scale well in relational databases.
If they're proper timestamp fields, I think you can also bypass the conversion and use something like:
where d_send_items.si_send_date >= '01-04-2015'
and d_send_items.si_send_date < '08-05-2015'
(noting the < day following bit for the second conditional since 08-05-2015 is the same as 08-05-2015 00:00:00) assuming MySQL will recognise those date formats as dd-mm-yyyy.
However, even if it doesn't and you have to use some function to turn those string into timestamp values, this is something that would be done once for the whole query rather than (most likely) for every single row.

WHERE clause to filter times that are under an hour

SELECT
name,
start_time,
TIME(cancelled_date) AS cancelled_time,
TIMEDIFF(start_time, TIME(cancelled_date)) AS difference
FROM
bookings
I'm trying to get from the database a list of bookings which were cancelled with less than an hour's notice. The start time and the cancellation times are both in TIME format, I know a timestamp would have made this easier. So above I've calculated the time difference between the two values and now need to add a WHERE clause to restrict it to only those records that have a difference of under 1:00:00. Obviously this isn't a number, it's a time, so a simple bit of maths won't do it.
start_time is a TIME
cancelled_date is a DATETIME but I'm converting it to TIME in the query to then calculate cancelled_time and difference.
I would be inclined to do this by adding and hour to the notice, something like this:
WHERE start_time > date_add(cancelled_date, interval 1 hour)
I can't quite tell what the right logic is from the question, because your column names don't match the description.
In this case, so a subtraction or doing the comparison are similar performance wise. But, if you had a constant instead of cancelled_date, then there is a difference. The following:
WHERE start_time < date_add(now(), interval -1 hour)
Allows the engine to use an index on start_time.
you can use having difference<time('1:00')

What is better: select date with trunc date or between

I need to create a query to select some data of my mysql db based on date, but in my where clause i have to options:
1 - trunc the date:
select count(*) from mailing_user where date_format(create_date, '%Y-%m-%d')='2013-11-05';
2 - use between
select count(*) from mailing_user where create_date between '2013-11-05 00:00:00' and '2013-11-05 23:59:59';
the two query's will work, but whats the better? Or, what's recommended? Why?
Here is an article to read.
http://willem.stuursma.name/2009/01/09/mysql-performance-with-date-functions/
If your created_date column is indexed, the 2nd query will be faster.
But if the column is not indexed and if this is your defined date format, you can use the following query.
select count(*) from mailing_user where DATE(create_date) = '2013-11-05';
I use DATE instead of DATE_FORMAT as I can make use of the native feature of getting in this format('2013-11-05').
From your question it seems you want to select records from one day, according to the documentation A DATETIME or TIMESTAMP value can include a trailing fractional seconds part in up to microseconds (6 digits) precision.
So this means your second query might actually get unlucky and miss some records that were inserted into the table at the very last second of that day, so that is why I would say the first one is more precise and is guaranteed to always get you the correct result.
The downside of this is that you cannot index that column using the date_format-function, because MySQL isn't cool with that.
If you don't want to use date_format and get around the precision issue you would change
where create_date between '2013-11-05 00:00:00' and '2013-11-05 23:59:59'
into
where create_date >= '2013-11-05 00:00:00' and create_date < '2013-12-05 00:00:00'
Number 2 will be faster if you have an index on the create_date because number one won't be able to use the index to quickly scan the results.
However this requires there to be an index on the create_date.
Otherwise I imagine they would be similar speed, possibly the second would still be faster because of the smaller processing time to compare(datetime comparison rather than converting to a string and comparing strings), but I doubt it'd be significant.