How can I query from 2 dates ranges (mysql) - mysql

I want to pull the emails from 40 days ago and 20 days ago, each range being 1 day. This is what I have but it returns no rows.
SELECT s.*, r.email FROM sellyourcar s
INNER JOIN register r ON s.rid = r.slno
WHERE s.dt BETWEEN DATE_SUB(curdate(),INTERVAL 20 DAY) AND DATE_SUB(curdate(), INTERVAL 19 DAY) AND
s.t BETWEEN DATE_SUB(curdate(),INTERVAL 40 DAY) AND DATE_SUB(curdate(), INTERVAL 39 DAY)

You should be using an OR instead of and for your two intervals:
SELECT s.*, r.email
FROM sellyourcar s INNER JOIN register r ON s.rid = r.slno
WHERE s.dt BETWEEN DATE_SUB(curdate(),INTERVAL 20 DAY) AND DATE_SUB(curdate(), INTERVAL 19 DAY)
OR s.dt BETWEEN DATE_SUB(curdate(),INTERVAL 40 DAY) AND DATE_SUB(curdate(), INTERVAL 39 DAY)
As another note, at least in Oracle, I am not sure about in MYSQL the BETWEEN functions returns items matching the end items also. For example between 3 and 5 would also return items that were 3 and 5 and not just 4. So you may want to just to check if the date of the email is 20 or 40 days less than the current date.

Related

How to group date between two past date in one column MYSQL

I have this Query
SELECT
DATE_ADD(table1.date, INTERVAL -7 DAY) AS date7,
DATE_ADD(table1.date, INTERVAL -14 DAY) AS date14,
DATE_ADD(table1.date, INTERVAL -21 DAY) AS date21,
table1.hotel AS hotel,
table1.customer AS Customer,
table1.date AS Date,
table1.sell AS Sells,
table2.adr AS ADR,
table2.revpar AS RevPAR,
table3.name_hotel AS Hotel_name,
FROM `table1`
INNER JOIN table3 ON table1.hotel=table3.hotel
INNER JOIN table2
ON table1.hotel=table2.hotel
AND table1.date_occ=table2.date_occ
I would like to get a column "weeks" where Date in between Date and date7 then "last week", Date between date7 and date14 then "-2 week" and Date between in date14 and date21 then "-3week". Because I need to group in "weeks" to calculate sells last 7 days, 14 days and 21 days according current date
Something like this should work.
table1.date BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW()
table1.date BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY) AND DATE_SUB(NOW(), INTERVAL 7 DAY)
table1.date BETWEEN DATE_SUB(NOW(), INTERVAL 21 DAY) AND DATE_SUB(NOW(), INTERVAL 14 DAY)
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-sub

MySQL - Get Aggregates For Last 1 Day, 7 Days, 30 Days And Allow For Records To Be Counted In More Than 1 Group

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

MySQL Where date between 9 and 10 days

I'm trying to make a query that will select all my users who's donor status is ending within 10 days.
As i only want to send the message once I want to select all the users who has their donor status ending between 10 and 9 days ahead.
The Donor end date is in this format: 0000-00-00 00:00:00
This is the query I'm currently working around with:
SELECT UserID FROM users_info WHERE donorEnd BETWEEN (NOW() + INTERVAL 10 DAY) AND (NOW() + INTERVAL 9 DAY)
I think you problem is that you are adding a time not a date: NOW() + INTERVAL 9 DAY = 2015-02-27 19:19 not 2015-02-27 00:00
Try use ADDDATE with CURDATE():
SELECT UserID FROM users_info WHERE donorEnd BETWEEN DATE_ADD(CURDATE(), INTERVAL 9 DAY) AND DATE_ADD(CURDATE(), INTERVAL 9 DAY)

Grouping date of births in 2 month periods

I'm running a simple query that's returning the number of children turning 2 (birthday last month or next month). The following query returns a single row with count:
SELECT COUNT(*)
FROM table AS t
-- Child turning 2
AND t.dob <= DATE_SUB(NOW(), INTERVAL 23 MONTH)
AND t.dob >= DATE_SUB(NOW(), INTERVAL 25 MONTH)
I'd like to be able to build on this query and return multiple count rows, each for a 2 month period so that I can predict 2nd birthdays moving forward.
I could do something like this:
SELECT COUNT(*)
FROM table AS t
-- Child turning 2
AND t.dob <= DATE_SUB(NOW(), INTERVAL 23 MONTH)
AND t.dob >= DATE_SUB(NOW(), INTERVAL 25 MONTH)
UNION
SELECT COUNT(*)
FROM table AS t
-- Child turning 2
AND t.dob <= DATE_SUB(NOW(), INTERVAL 21 MONTH)
AND t.dob >= DATE_SUB(NOW(), INTERVAL 23 MONTH)
UNION...
But this is stupidly inefficient and very clumsy.
As an output I'd like to see something like this:
count |date range
---------------------------------
327 |2012-03-01 - 2012-04-31
---------------------------------
532 |2012-05-01 - 2012-06-31
I think I need to do something with GROUP BY but am unsure about how to go about this.
Many thanks.
select
case
when t.dob between date_sub(now(), interval 25 month) and date_sub(now(), interval 23 month) then 'between -25 and -23 month'
when t.dob between date_sub(now(), interval 22 month) and date_sub(now(), interval 20 month) then 'between -22 and -20 month'
when t.dob between date_sub(now(), interval 19 month) and date_sub(now(), interval 17 month) then 'between -19 and -17 month'
when t.dob between date_sub(now(), interval 16 month) and date_sub(now(), interval 14 month) then 'between -16 and -14 month'
end as my_ranges,
count(*)
from
t
group by my_ranges

SQL Hourly Data

The query below retrieves weather data from a MySql database, and groups this data in to an hourly format.
select hour(datetime) AS hour
, avg(Temperature) as AVGT
from Database.minute
WHERE DATETIME
BETWEEN (CURDATE() + INTERVAL (SELECT hour(NOW())) hour - INTERVAL 23 hour)
AND ((CURDATE() + INTERVAL (SELECT hour(NOW())) hour))
group by hour
order by (CURDATE() + INTERVAL (SELECT hour(NOW())) hour - INTERVAL 23 hour)
Output is as follows:
hour AVGT
19 11.730
20 11.970
21 11.970
22 11.760
23 11.660
0 11.700
1 11.830
2 12.370
3 12.770
4 12.840
5 12.840
6 12.540
7 12.500
8 12.030
9 12.100
10 12.300
11 12.060
12 11.090
13 10.920
14 10.920
15 10.820
16 10.760
17 10.690
18 10.560
The time is now 18:15. All of the above output is correct apart from the data gathered for hour '18'. Instead of getting the average value between 18:00 and 18:15, it just outputs the average at time 18:00. ie. ignoring data between 18:01 and 18:14.
How can I modify the above query to include data in the current hour (18:00 to Now)?
Thanks
Why don't you simply try
SELECT Hour(datetime) AS hour,
Avg(temperature) AS AVGT
FROM DATABASE.minute
WHERE datetime BETWEEN ( Curdate() + INTERVAL (SELECT Hour(Now())) hour -
INTERVAL 23 hour ) AND Now()
GROUP BY hour
ORDER BY ( Curdate() + INTERVAL (SELECT Hour(Now())) hour - INTERVAL 23 hour )
I agree with #Ankur's answer (your filter citerion should not filter records up to the current hour, but rather the current time), however your date/time operations are very strange:
You don't need a subquery (SELECT Hour(NOW())) to obtain HOUR(NOW());
You can express ( Curdate() + INTERVAL (SELECT Hour(NOW())) hour - INTERVAL 23 hour ) more simply:
CURDATE() + INTERVAL HOUR(NOW()) - 23 HOUR
Or, in my view, more clearly:
DATE_FORMAT(NOW() - INTERVAL 23 HOUR, '%Y-%m-%d %H:00:00')
Your ORDER BY clause is a constant and therefore achieves nothing: did you mean to order by hour?
Therefore:
SELECT HOUR(datetime) AS hour,
AVG(Temperature) AS AVGT
FROM Database.minute
WHERE datetime BETWEEN
DATE_FORMAT(NOW() - INTERVAL 23 HOUR, '%Y-%m-%d %H:00:00')
AND NOW()
GROUP BY hour
ORDER BY hour