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())
Related
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
Given a set of data with date_created stored like 2017-04-13 23:29:52, how would I construct an SQL query to select all items that were created within the last 3 hours?
I originally thought to do something like this:
SELECT
*,
MAX(date_created)
FROM items
GROUP BY date_created
but that would not be exactly what I want. I'm not sure how to go about this.
Use NOW() and INTERVAL in your WHERE clause
SELECT * FROM items WHERE date_created <= NOW() - INTERVAL 180 minute AND date_created >= NOW() - INTERVAL 210 minute
This one uses CURDATE, CURDATE and DATE_ADD:
SELECT *
FROM items
WHERE DATE(date_created) = CURDATE()
AND TIME(date_created) BETWEEN CURTIME() AND DATE_ADD(CURTIME(), INTERVAL -3 HOUR)
select * from items where
extract(hours from age(current_timestamp, date_created))>=3;
Extract keyword would extract hours difference from current timestamp and return only that is greater than or equal to 3.
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?
Suppose you have a table of the form:
create table user_activity (
user_id int not null,
activity_date timestamp not null,
...);
It's easy enough to select the number of unique user_id's in the past 30 days.
select count(distinct user_id) from user_activity where activity_date > now() - interval 30 day;
But how can you select the number of unique user_ids in the prior 30 days for each of the past 30 days? E.g. uniques for 0-30 days ago, 1-31 days ago, 2-32 days ago and so on to 30-60 days ago.
The database engine is mysql if it matters
You could try using a sub query:
SELECT DISTINCT `activity_date` as `day`, (
SELECT count(DISTINCT `user_id`) FROM `user_activity` WHERE `activity_date` = `day`
) as `num_uniques`
FROM `user_activity`
WHERE `activity_date` > NOW() - INTERVAL 30 day;
This should give you the number of unique users for each day. However, I haven't tested this since I don't have the DB to work with.
I haven't tried this in MySQL, but hopefully the syntax is right. If not, maybe it will point you in the right direction. First, I often employ a Numbers table. It can be a physical table simply made up of numbers or it can be a generated/virtual/temporary table.
SELECT
N.number,
COUNT(DISTINCT UA.user_id)
FROM
Numbers N
INNER JOIN User_Activity UA ON
UA.activity_date > NOW() - INTERVAL 30 + N.number DAY AND
UA.activity_date <= NOW() - INTERVAL N.number DAY
WHERE
N.number BETWEEN 0 AND 30
GROUP BY
N.number
I'm not familiar with the whole INTERVAL syntax, so if I got that wrong, please let me know and I'll try to correct it.
If you get the days number for todays date and mod it by 30 you get the offset of the current day. Then you add that to each number for a date and divide the result by 30, this gives you the group of days. Then group your results by this number. So in code something like this:
select count(distinct user_id), (to_days(activity_date)+(to_days(now()) % 30)) / 30 as period
from user_activity
group by (to_days(activity_date)+(to_days(now()) % 30)) / 30
I will leave calculating the reverse numbering of period up to you (hint: take the period number for the current date as "max" and subtract period above and add 1.)
I always have trouble with complicated SQL queries.
This is what I have
$query = '
SELECT id,
name,
info,
date_time
FROM acms_events
WHERE date_time = DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND active = 1
ORDER BY date_time ASC
LIMIT 6
';
I want to get up to 6 rows that are upcoming within the hour. Is my query wrong? It does not seem to get events that are upcoming within the next hour when I test it.
What is the correct syntax for this?
I'm going to postulate that you're looking at a group of records that contain a range of DATETIME values, so you probably want something more like this:
SELECT id,
name,
info,
date_time
FROM acms_events
WHERE date_time < DATE_ADD(NOW(), INTERVAL 1 HOUR)
AND date_time >= NOW()
AND active = 1
ORDER BY date_time ASC
LIMIT 6
Otherwise, your query is looking for records with a date_time of exactly "now + 1 hour". I'm assuming all your dates aren't specific to that particular second. ;)
To clarify a bit, DATE_ADD() and DATE_SUB() return exact timestamps, so your query above roughly translates to something like SELECT ... WHERE date_time = '2010-04-14 23:10:05' ORDER BY ..., which I don't think is what you want.
WHERE date_time = DATE_SUB(NOW(), INTERVAL 1 HOUR)
means date_time equals exactly now minus one hour, which would result in any record exactly one hour old.
Why not use
WHERE TIMEDIFF(date_time, NOW()) < '01:00:00'
AND date_time > NOW()