I am trying to get back rows that are between year ranges, such as from 0-5 years, 5-10 years, 10-15 etc.
So far, I've only been able to product between 0-5 but need some help on querying between 5-10 years etc.
SELECT *
FROM users
WHERE start_date >= DATE_SUB(NOW(),INTERVAL 5 YEAR)
I've tried using the BETWEEN function, but could be using it incorrectly. Open to suggestions.
I'm not a fan of hard coding values in for the dates because I don't want to go back every few years and change it.
Assuming start_date is DATE datatype (not DATETIME or TIMESTAMP)
five years ago up to today
WHERE start_date > DATE(NOW()) + INTERVAL -5 YEAR
AND start_date <= DATE(NOW()) + INTERVAL 0 YEAR
ten years ago up to five years ago
WHERE start_date > DATE(NOW()) + INTERVAL -10 YEAR
AND start_date <= DATE(NOW()) + INTERVAL -5 YEAR
You can use BETWEEN.
SELECT *
FROM users
WHERE (start_date BETWEEN NOW() AND DATE_SUB(NOW(), INTERVAL 5 YEAR))
and then for your next interval:
SELECT *
FROM users
WHERE (start_date BETWEEN DATE_SUB(NOW(), INTERVAL 5 YEAR) AND DATE_SUB(NOW(), INTERVAL 10 YEAR))
0 - 5
SELECT * FROM users
WHERE
start_date BETWEEN (CURDATE() - INTERVAL 5 YEAR) AND CURDATE();
5 - 10
SELECT * FROM users
WHERE
start_date BETWEEN (CURDATE() - INTERVAL 10 YEAR) AND (CURDATE() - INTERVAL 5 YEAR);
10 - 15
SELECT * FROM users
WHERE
start_date BETWEEN (CURDATE() - INTERVAL 15 YEAR) AND (CURDATE() - INTERVAL 10 YEAR);
Related
How to select all data from last month (or 30 days)?
I already found some answers, and mostly gives this solution
SELECT *
FROM gigs
WHERE date > DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
ORDER BY date DESC
But this gives me also the dates from the future
I am only interested in the days from last month or 30 days (not next month and beyond)
Is this what you want?
WHERE date > DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND date <= CURRENT_DATE
I added a condition so the query filters on date not greater than today. I also modified your code so the date range starts one month ago (you had 3 months).
try this code
SELECT * FROM gigs
WHERE date BETWEEN CURDATE() - INTERVAL 30 DAY AND CURDATE()
ORDER BY date DESC
You are asking for two separate things.
The last 30 days is easy.
date between now() - interval 30 day and now()
Data this month is like this:
date between (last_day(Now() - INTERVAL 1 MONTH) + INTERVAL 1 DAY) and last_day(Now())
Data a few months ago is like this:
date between (last_day(Now() - INTERVAL 4 MONTH) + INTERVAL 1 DAY)
and
(last_day(Now() - INTERVAL 3 MONTH) + INTERVAL 1 DAY)
I have a table with the following data:
I am looking to group the rows into the following:
Within the last day (everything within the last 24 hours)
Within the last 7 days (everything within the last week)
Within the last 30 days (everything within the last month)
The end result for the above rows would look something like:
I can group the records into these brackets right now with:
SELECT (CASE WHEN created_at = CURDATE() THEN '1 Day'
WHEN created_at >= CURDATE() - INTERVAL 6 DAY THEN '7 Days'
WHEN created_at >= CURDATE() - INTERVAL 29 DAY THEN '30 Days'
END) AS Timeframe, COUNT(*) AS Count
FROM my_table
GROUP BY (CASE WHEN created_at = CURDATE() THEN '1 Day'
WHEN created_at >= CURDATE() - INTERVAL 6 DAY THEN '7 Days'
WHEN created_at >= CURDATE() - INTERVAL 29 DAY THEN'30 Days'
END)
But this will prevent individual records from being counted more than once. For example, lines 2 and 3 in the first picture needs to be counted in all three brackets (1 day, 7 days, and 30 days) - while lines 6 through 9 only needs to be counted in the 30 days bracket.
How would you do this with MySQL?
It is easiest to do this as columns, rather than rows:
SELECT SUM(created_at = CURDATE()) as today
SUM(created_at >= CURDATE() - INTERVAL 6 DAY) as last_7_days,
SUM(created_at >= CURDATE() - INTERVAL 29 DAY) as last_30_days,
SUM(created_at < CURDATE() - INTERVAL 29 DAY) as older
FROM my_table;
If you want your response in several rows, instead of just one with several columns, take #Gordon Linoff as your starting point... but perform the queries "one row at at time" (it won't be as efficient, because you visit the table 4 times instead of 1!):
-- Row for the 1 day timeframe
SELECT '1 Day' AS `Timeframe`, SUM(created_at = CURDATE()) AS `Count`
FROM my_table
UNION
-- Row for the 7 days timeframe...
SELECT '7 Days' AS `Timeframe`, SUM(created_at >= CURDATE() - INTERVAL 6 DAY) AS `Count`
FROM my_table
UNION
SELECT '30 Days' AS `Timeframe`, SUM(created_at >= CURDATE() - INTERVAL 29 DAY) AS `Count`
FROM my_table
UNION
SELECT 'Older' AS `Timeframe`, SUM(created_at < CURDATE() - INTERVAL 29 DAY) AS `Count`
FROM my_table ;
If you can use MariaDB instead of MySQL, you can use a WITH, which will allow the query to be efficient again:
WITH stats AS
(
SELECT SUM(created_at = CURDATE()) as today,
SUM(created_at >= CURDATE() - INTERVAL 6 DAY) as last_7_days,
SUM(created_at >= CURDATE() - INTERVAL 29 DAY) as last_30_days,
SUM(created_at < CURDATE() - INTERVAL 29 DAY) as older
FROM my_table
)
-- Convert to rows with negligible overhead
SELECT '1 Day' AS `Timeframe`, today FROM stats
UNION
SELECT '7 Days', last_7_days FROM stats
UNION
SELECT '30 Days', last_30_days FROM stats
UNION
SELECT 'Older', older FROM stats ;
In both cases, you'll get (as of 2017-07-25):
Timeframe | today
:-------- | ----:
1 Day | 0
7 Days | 4
30 Days | 8
Older | 0
dbfiddle here
I have a subscriptions table with an associated feed_id and creation timestamp. A feed has N subscriptions.
It's easy enough to show the most popular feeds using a group query to count the number of records with each feed_id. But I want to calculate momentum to show most trending feeds.
A simplified algorithm would be:
momentum of feed_id =
10 * (count of subscriptions with created_at in past day)
+ 5 * (count of subscriptions with created_at from 2-7 days ago)
+ 1 * (count of subscriptions with created_at from 7-28 days ago)
How can something like this be done in a single (My)SQL query instead of doing it with 3 queries and programmatically summing the results?
You can use conditional aggregation for this. MySQL treats booleans as integers, with true being "1", so you can just sum the expression for time.
I am guessing it looks something like this:
select feedid,
(10 * sum(createdat >= date_sub(now(), interval 1 day)) +
5 * sum(createdat >= date_sub(now(), interval 7 day) and
createdat < date_sub(now(), interval 1 day)) +
1 * sum(createdat >= date_sub(now(), interval 28 day) and
createdat < date_sub(now(), interval 7 day))
) as momentum
from subscriptions
group by feedid
SELECT 10*COUNT(IF(created_at >= CURDATE(), 1, 0)) +
5*COUNT(IF(created_at BETWEEN DATE_ADD(CURDATE(), - INTERVAL 7 days) AND DATE_ADD(CURDATE(), - INTERVAL 1 day), 1, 0) +
1*COUNT(IF(created_at BETWEEN DATE_ADD(CURDATE(), - INTERVAL 28 days) AND DATE_ADD(CURDATE(), - INTERVAL 8 day), 1, 0)
FROM ...
I'm not 100% sure I've caught the edge conditions (yesterday or 8 days ago) to get exactly the right count. You'll want to test that.
If you're interested in 24-hour periods then just substitute NOW() for CURDATE() and everything will go to DATETIME.
I have a requirement to compare the last 24h with the same period a year ago.
If I do:
event_date < now() - INTERVAL 365 DAY and event_date > now() - INTERVAL 366 DAY
it does not take into consideration leap years.
The where clause you would need to create the condition for the records a year ago would be:
WHERE event_date >= DATE_SUB(DATE_SUB(NOW(), INTERVAL 1 YEAR), INTERVAL 24 HOUR)
AND event_date <= DATE_SUB(NOW(), INTERVAL 1 YEAR)
By doing it this way you will not have to worry about the leap years.
To get the data for the current past 24 hours you would use:
WHERE event_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND event_date <= NOW()
try
event_date < now() - INTERVAL 1 YEAR
AND event_date > now() - INTERVAL 1 YEAR - INTERVAL 1 DAY
or try
event_date BETWEEN (now() - INTERVAL 1 YEAR - INTERVAL 1 DAY)
AND (now() - INTERVAL 1 YEAR)
How can select the last records added in 5 seconds, 5 minutes, 5 hours, 5 days, 5 weeks, 5 months, 5 years in one query?
Is it possible to be selected in one query?
sample records include
name | added_timestamp
v | last_five_minutes
k | last_hour
l | last_hour
the timestamps can be pseudo for the actual time
Although you haven't stated it, I suspect you want totals for the various time periods:
SELECT
SUM(date_added > NOW() - INTERVAL 5 SECOND) as total_in_last_5_seconds,
SUM(date_added > NOW() - INTERVAL 5 MINUTE) as total_in_last_5_minutes,
SUM(date_added > NOW() - INTERVAL 5 HOUR) as total_in_last_5_hours,
SUM(date_added > NOW() - INTERVAL 5 DAY) as total_in_last_5_days,
SUM(date_added > NOW() - INTERVAL 5 WEEK) as total_in_last_5_weeks,
SUM(date_added > NOW() - INTERVAL 5 MONTH) as total_in_last_5_months,
SUM(date_added > NOW() - INTERVAL 5 YEAR) as total_in_last_5_years
from records;
Edited: Added alternative prompted by comment
If you want the actual records, this will categorize them:
SELECT
*,
case
when date_added > NOW() - INTERVAL 5 SECOND then 'last_5_seconds'
when date_added > NOW() - INTERVAL 5 MINUTE then 'last_5_minutes'
when date_added > NOW() - INTERVAL 5 HOUR then 'last_5_hours'
when date_added > NOW() - INTERVAL 5 DAY then 'last_5_days'
when date_added > NOW() - INTERVAL 5 WEEK then 'last_5_weeks'
when date_added > NOW() - INTERVAL 5 MONTH then 'last_5_months'
when date_added > NOW() - INTERVAL 5 YEAR then 'last_5_years'
else 'ancient'
end as time_category
from records;
SELECT
*, /* now just don't be lazy but specify whatever columns you want to pull */
(Timestamp >= NOW() - INTERVAL 5 SECOND) AS AddedWithinSeconds,
(Timestamp >= NOW() - INTERVAL 5 MINUTE) AS AddedWithinMinutes,
(Timestamp >= NOW() - INTERVAL 5 HOUR) AS AddedWithinHours,
(Timestamp >= NOW() - INTERVAL 5 DAY) AS AddedWithinDays,
(Timestamp >= NOW() - INTERVAL 5 WEEK) AS AddedWithinWeeks,
(Timestamp >= NOW() - INTERVAL 5 MONTH) AS AddedWithinMonths
FROM atable
WHERE Timestamp >= NOW() - INTERVAL 5 YEAR
ORDER BY
AddedWithinSeconds DESC,
AddedWithinMinutes DESC,
AddedWithinHours DESC,
AddedWithinDays DESC,
AddedWithinWeeks DESC,
AddedWithinMonths DESC
Get the last records added in 5 years:
SELECT * FROM records WHERE date_added > NOW() - INTERVAL 5 YEAR
Then extract the records added in 5 seconds, 5 minutes, 5 hours, 5 days, 5 weeks, 5 months from the results.