How to group date between two past date in one column MYSQL - 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

Related

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

SQL: Show "running" events

my script shows the events of the next 14 days:
SELECT
*
FROM
events
WHERE
eventdate
BETWEEN CURDATE() AND DATE_ADD(NOW(), INTERVAL 14 DAY)
This works fine so far BUT at midnight all "running" (night)events are not displayed anymore.
So the query should output the events from the day before till 5 a.m.
This is my idea but it doesn't work:
SELECT
*
FROM
events
WHERE
eventdate
BETWEEN DATE_SUB(CURDATE(), INTERVAL 5 HOUR)
AND
DATE_ADD(NOW(), INTERVAL 14 DAY)
Is it because 'eventdate' is a DATE-field?
Thanks!
It sounds like you want to subtract 5 hours before doing the comparison:
WHERE date_sub(eventdate, interval 5 hour) BETWEEN CURDATE() AND DATE_ADD(NOW(), INTERVAL 14 DAY)
Alternatively, you can add 5 hours on the other side:
where eventdate between now() and datea_add(now(), interval 14*24 + 5 hour)
This should do the job or not!?
WHERE
eventdate
BETWEEN DATE(DATE_SUB(NOW(), INTERVAL 5 HOUR))
AND
DATE_ADD(NOW(), INTERVAL 14 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

get 2 days ago query in mysql

So for getting last 24 hours query I use something like this
SELECT COUNT(*) AS cnt FROM `mytable` WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
where timestamp is a table field with timestamps.
but how can I get the interval between 2 days ago and yesterday.
So
today is 24 ian. I want a query between 22 ian (00:00am) and 23 ian (00:00am)
WHERE timestamp BETWEEN
DATE_SUB(DATE(NOW()), INTERVAL 2 DAY)
AND DATE_SUB(DATE(NOW()), INTERVAL 1 DAY)
You can also try DATE_ADD with a minus interval ;)
WHERE timestamp BETWEEN
DATE_ADD(DATE(NOW()), INTERVAL -2 DAY)
AND DATE_ADD(DATE(NOW()), INTERVAL -1 DAY)
Use Interval
WHERE `timestamp`
BETWEEN DATE_SUB(NOW(), INTERVAL 2 DAY)
AND DATE_SUB(NOW(), INTERVAL 1 DAY)
If you want a query between 22 Jan (00:00 AM) and 22 Jan (11:59 PM)
where DATE(timestamp) = DATE_SUB(DATE(now()), INTERVAL 2 day);
Example:
timestamp = 2020-02-24 12:07:19 and Date(timestamp) is 2020-02-24 and now() output is current date with time when we use DATE(now()) then output is Date only,
DATE_SUB(DATE(now()), INTERVAL 2 day)
is will be 2 days ago.
Try BETWEEN::
SELECT
COUNT(*) AS cnt
FROM `mytable`
WHERE timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 2 DAY) and DATE_SUB(NOW(), INTERVAL 1 DAY)

How can I query from 2 dates ranges (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.