Is typing date as string faster than using CURDATE() - mysql

I'm writing a mysql query that finds all the records created in the last 90 days. Does it make any difference in terms of speed to use:
SELECT user_id
FROM users
WHERE created_at > '2016-06-16'
compared to:
SELECT user_id
FROM users
WHERE created_at > date_sub(curdate(), interval 90 day)
Is there another way that would be even faster?

Related

Selecting records from last 24 hours - MySQL

I'm trying to run this MySQL command to select records with a lead_submitted date in the last 24 hours.
The issue is it grabs future dates too (fyi I'm delaying some leads so basically set a date in the future for these to be processed).
For example, if I run the command:
SELECT id, lead_submitted, processed FROM leads WHERE (lead_submitted > now() - INTERVAL 24 HOUR) ORDER BY id DESC;
I get this result:
10 | 2022-10-04 13:24:13 | N
~
Why is this? I just want to select records from the last 24h.
FTR, when I run SELECT NOW() as now; I get 2022-09-30 14:00:12
Any help would be greatly appreciated.
EDIT:
I've found this works as a workaround, but it feels nasty:
SELECT id, lead_submitted, processed FROM leads WHERE (lead_submitted > now() - INTERVAL 24 HOUR) AND (lead_submitted < now() + INTERVAL 1 SECOND) AND processed = 'N' ORDER BY id DESC LIMIT 1;
You probably want to use:
SELECT id, lead_submitted, processed
FROM leads
WHERE lead_submitted between (now() - INTERVAL 24 HOUR) and now()
ORDER BY id DESC;

How can I add days to a date in MYSQL in a query

I am trying to add 5 days to a date in MYSQL in a query. This is what I have done:
SELECT * FROM sales INNER JOIN partner on user_id = idpartner WHERE DATE((end_date) + 5) >= DATE(NOW()) ORDER BY end_date ASC LIMIT 0,50000
But this is not showing the list of sales which has ended. Can someone please tell me where I am making a mistake.
It looks like you want rows where end_date is later than five days ago.
The best way to get that is with
WHERE end_date >= CURDATE() - INTERVAL 5 DAY
The business of adding integers to dates doesn't work in MySQL (it's an Oracle thing). So you need to use the INTERVAL n unit syntax.
You'll notice that my WHERE clause above is functionally equivalent to
WHERE DATE(end_date) + INTERVAL 5 DAY >= DATE(NOW())
But, the first formulation is superior to the second for two reasons.
if you mention end_date in a WHERE clause without wrapping it in computations, your query can exploit an index on that column and can run faster.
DATE(NOW()) and CURDATE() both refer to the first moment of today (midnight). But CURDATE() is a bit simpler.
To fix the original query, you can use DATE_ADD with the INTERVAL keyword:
SELECT
*
FROM
sales
INNER JOIN
partner ON user_id = idpartner
WHERE
DATE_ADD(end_date, INTERVAL 5 DAY) >= DATE(NOW())
ORDER BY end_date ASC
LIMIT 0 , 50000
Said that, I wouldn't recommend applying functions such as DATE_ADD on columns, as it means that the database won't be able to use an index on end_date. Therefore, I would modify the query to:
SELECT
*
FROM
sales
INNER JOIN
partner ON user_id = idpartner
WHERE
end_date <= DATE_ADD(DATE(NOW()), INTERVAL 5 DAY)
ORDER BY end_date ASC
LIMIT 0 , 50000
As you can see, in the second alternative all functions are applied on constants and not on columns (end_date).
You can try
DATE_ADD() here is the
Link
Select DATE_ADD(DATE_FORMAT(NOW(),'%Y-%m-%d'),INTERVAL 1 DAY) FROM DUAL

mysql optimize query where date hour

Hi all, I have pretty awfull query, that needs optimizing.
I need to select all records where date of created matches NOW - 35days, but the minutes and seconds can be any.
So I have this query here, its ugly, but working:
Any optimisation tips are welcome!
SELECT * FROM outbound_email
oe
INNER JOIN (SELECT `issue_id` FROM `issues` WHERE 1 ORDER BY year DESC, NUM DESC LIMIT 0,5) as issues
ON oe.issue_id = issues.issue_id
WHERE
year(created) = year( DATE_SUB(NOW(), INTERVAL 35 DAY) ) AND
month(created) = month( DATE_SUB(NOW(), INTERVAL 35 DAY) ) AND
day(created) = day( DATE_SUB(NOW(), INTERVAL 35 DAY) ) AND
hour(created) = hour( DATE_SUB(NOW(), INTERVAL 35 DAY) )
AND campaign_id IN (SELECT id FROM campaigns WHERE initial = 1)
I assume the field "created" is a datetime field and is from the issues table? Since you don't need anything else on the issues and campaign table, then you can do the following:
SELECT e.* FROM outbound_email e
JOIN issues i ON e.issue_id = i.issue_id
JOIN campaigns c ON c.id = i.campaign_id
WHERE i.created < DATE_SUB(NOW(), INTERVAL 35 DAY)
AND c.initial = 1
There's no need to separate the datetime field into years, months...etc.
You seem to be saying you want to select all rows from a table where the time they were created was the same hour as it is currently, 35 days ago
SELECT * FROM table WHERE created BETWEEN
DATE_ADD(CURDATE(), INTERVAL (HOUR(now()) - 840) HOUR) AND
DATE_ADD(CURDATE(), INTERVAL (HOUR(now()) - 839) HOUR)
Why does it work? Curdate gives us today at midnight. We add to this the current hour of the time (e.g. Suppose it's now 5pm we'd add `HOUR(NOW()) which would give us 17, for a time now of 5pm) but we also subtract 840 because that's 35 days * 24 hours a day = 840 hours. Date add will hence add -823 hours to the current date, i.e. 5pm 35 days ago
We make the search a range to get all the records from the hour, the simplest way to specify an hour later is to subtract 839 hours instead of 840
Technically this query will also return records that are bang on 6pm (but not a second later) 35 days ago too because between is inclusive (between 1 and 10 will return 10 also
If this is a problem, change the BETWEEN for created >= blah AND created < blahblah
I haven't put the rest of your query in for reasons of clarity
As a side note, the way you did it wasn't bad- you could have simplified things by not having the year/month/day parts, just dropping the time part of the date with date(created) = date_sub(curdate(), interval 35 day) which is the year month and day combined as a date, no time element.. BUT it is generally always best to leave table data alone rather than format or convert it just to match a query. If you convert table data then indexes can no longer be used. If you go the extra mile to get your query parameters into the format of the column, and don't convert the table data then indexes on the column can be used

Mysql query date between in large table

my query is running about 10 seconds and that's unacceptable.
I am looking for a way to improve this speed but i'm out of options.
I have to find the records between now and 30 days back in a table over 12 million rows.
The following query:
SELECT DATE(DATE) AS FDATE,
SUM(VIEW_COUNT) AS COUNT,
COUNT(IP_ADDRESS) AS CLIENTS
FROM VIEWS
WHERE USERID = 'test'
AND DATE BETWEEN ADDDATE(CURDATE(), INTERVAL -30 DAY) AND CURDATE()
GROUP BY FDATE DESC
I also tried, but the same effect:
SELECT DATE(DATE) AS FDATE,
SUM(VIEW_COUNT) AS COUNT,
COUNT(IP_ADDRESS) AS CLIENTS
FROM VIEWS
WHERE USERID = 'test'
AND DATE >= (DATE(NOW() - INTERVAL 30 DAY) + INTERVAL 0 SECOND)
GROUP BY FDATE DESC
You could try using MySQL Indexes for a better performance in decreasing the query execution time.
http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

MySql - get days remaining

Users can sign up for a premium listing for a specified number of days, e.g. 30 days.
tblPremiumListings
user_id days created_date
---------------------------------
1 30 2013-05-21
2 60 2013-06-21
3 120 2012-06-21
How would I select records where there are still days remaining on a premium listing.
SELECT *
FROM tblPremiumListings
WHERE created_date + INTERVAL `days` DAY >= CURDATE()
It's easiest to read with INTERVAL
select *
from tblPremiumListings
where created_date + interval days day >= now();
But I would also change the table to instead of created_date and days instead store end_date. That way the query is
select *
from tblPremiumListings
where end_date >= now();
The benefit of doing like this is that you can put an index on end_date and quickly find all ended premium listings, with your original table you'll always have to do a full table scan to find the records with expired listing.
SELECT * FROM
tblPremiumListings
WHERE (DATEDIFF(NOW(), created_date) - days) <= 0
See if it solves your problem
One way to get the result:
SELECT t.user_id
, t.days
, t.created_date
FROM tblPremiumListings t
WHERE t.created_date + INTERVAL t.days DAY > DATE(NOW())
You may want a >= comparison operator (instead of >) depending on how you define days remaining.
NOTE: the access plan for this query will be full scan of all rows, since MySQL won't be able to do a range scan on an index. For large sets, having a column that can be indexed to satisfy the query may improve performance, e.g.
WHERE t.expire_date > DATE(NOW())
Try this one...
SELECT * FROM
tblPremiumListings
WHERE DATE_ADD(created_date, days)>DATE(NOW())