Rush Hour table for every day in a month MySQL - mysql

I'm trying to make a query to get rush hours for everyday on a specific month.
The table I have looks like this:
id idproduct created_at
1 021354684 2011-10-01 20:25:48
2 033546835 2011-10-01 20:30:15
3 055965654 2011-10-01 20:45:20
4 012975343 2011-10-02 14:03:36
5 021354684 2011-10-02 15:55:48
6 033546835 2011-10-02 16:30:15
7 055965654 2011-10-02 16:45:20
8 012975343 2011-10-02 18:53:36
9 021354684 2011-10-03 08:55:48
10 033546835 2011-10-03 09:30:15
11 055965654 2011-10-03 14:03:20
12 012975343 2011-10-03 14:03:36
What I try to get is something like this...:
day rush_hour number_of_rows
1 20:00 3
2 16:00 5
3 14:00 4
Is it possible to get a table like this? can you guys help me?
I made a mistake, sorry for this. The number of rows should be the total of items sold that day, not in that hour :( sorry.

http://sqlfiddle.com/#!2/5b87b/7
First, count every day's every hour's count (into a view, because we will use it twice below):
CREATE VIEW hours AS
SELECT
DATE( created_at ) AS d,
HOUR( created_at ) AS h,
COUNT(*) AS c
FROM item
GROUP BY DATE(created_at), HOUR(created_at);
Final query:
SELECT
hours.d AS `day`,
hours.h AS `rush_hour`,
hours.c AS `count`
-- get the max count for every day
FROM (
SELECT
d, -- the day
MAX(c) as c -- the count
FROM hours
GROUP BY d
) AS maxc
-- find the actual hour(s) with the max count for every day:
INNER JOIN hours ON hours.c = maxc.c
AND hours.d = maxc.d;

You're going to want to look at the MySQL Date Functions, they offer you some help with this
SELECT
day(created_at) as day,
hour(created_at) as rush_hour,
count(1) as num_rows
FROM item
GROUP BY
day(created_at), hour(created_at)
http://sqlfiddle.com/#!2/62a15/2/0

Try this:
SELECT dayofyear(created_at) as day, hour(created_at) as rush_hour, count(*) as number_of_rows
FROM table
GROUP BY dayofyear(created_at), hour(created_at);

Here it is without making a view:
SELECT ddd.day, eee.rush_hour, ddd.maxo
FROM
(select day, max(num_rows) as maxo from (
SELECT
day(created_at) as day,
hour(created_at) as rush_hour,
count(1) as num_rows
FROM item
GROUP BY
day(created_at), hour(created_at)
) as groupo group by day) as ddd
LEFT JOIN
(SELECT
day(created_at) as day,
hour(created_at) as rush_hour,
count(1) as num_rows
FROM item
GROUP BY
day(created_at), hour(created_at)
) as eee on ddd.day=eee.day and ddd.maxo=eee.num_rows
I could imagine it being formatted more nicely or having more relevant aliases, but there's just so much subselecting going on here.
And thanks SQLfiddlers for putting the data there.
And I think that if you have two hours tied for the highest number of whatever it is you are counting, they both will show up, so you'll get two (or more) records returned for that day of the month.

Related

mysql select top 10 of IDs by time period

Here is the table:
Id
time
QQa
2020-11-04 10:00:10
QQa
2020-11-05 20:17:04
QQa
2020-10-08 13:27:01
WWs
2020-10-09 14:08:44
WWs
2020-10-09 13:07:46
WWs
2020-10-09 13:26:57
RRe
2020-10-08 13:06:39
I'm trying to sort/get top 10 of such table by time diff. Here is the output I need (in days):
ID
Days
QQa
4
WWS
1
RRe
1
and so on...
So QQa took ~4 days others have timestamps within one day.
I'm trying to do it by something like this:
SELECT id, Min(time)
AS In Time, Max(time)
AS Out Time,
DATEDIFF(Max(time), Min(time))
AS Time Diff
FROM database.table GROUP BY id, DATE(time)
ORDER BY Time Diff ASC;
I'm afraid I'm not successful in what I'm doing. Any help is appreciated.
upd. https://stackoverflow.com/users/816613/nick-maroulis answer is the query I need. Thank you!
select ID, datediff( max(time), min(time) ) Days
from table
group by id
order by Days desc
limit 10

How to find whether the same customers who ordered this month also ordered the next month?

I have an orders table
Order_id User_id Order_date
1 32 2020-07-19
2 24 2020-07-21
3 27 2020-07-27
4 24 2020-08-14
5 32 2020-08-18
6 32 2020-08-19
7 58 2020-08-20
Now I want to find how many of the users ordered in 1st month also ordered in the next month. In this case, user_id's 32,24,27 ordered in 7th month but only 24 and 32 ordered in the next month.
I want the result to be like :
Date Retained_Users Total_users
2020-07 Null 3
2020-08 2 3
I'm lost here. Can someone please help me with this?
In MySQL 8.0, you can do this with window functions:
select
order_month,
count(distinct case when cnt_orders_last_month > 0 then user_id end) retained_users,
count(distinct user_id) total_users
from (
select
user_id,
date_format(order_date, '%Y-%m-01') as order_month,
count(*) over(
partition by user_id
order by date(date_format(order_date, '%Y-%m-01'))
range between interval 1 month preceding and interval 1 day preceding
) cnt_orders_last_month
from mytable
) t
group by order_month
The logic lies in the range specification of the window function; it orders record by month, and counts how many orders the customer placed last month. Then all that is left to do is aggregate and count distinct users.
Demo on DB Fiddle

Calculating aggregated number of days in each month in sql

I've got a table with multiple columns and two of the columns are start_date and end_date.
I need to calculate the number of days in each month. Let's assume I have following data in my table
id | start_date | end_date
1 04.01.2016 15.02.2016
2 07.01.2016 22.01.2016
3 16.05.2016 11.07.2016
I want an output as follows
Month | numberOfTravelDays
January 51
February 15
May 15
June 31
July 11
This output I am expecting is the number of total travel days each month has been utilized. I am having trouble constructing the sql query for this. Can someone assist me on this?
This is what I have for now. And it's not doing the job. The below query also filters only this year's records(but ignore that).
select MONTH(start_date) as month,
COUNT(DATEDIFF(start_date, end_date)) as numberOfTravelDays
from travel
where YEAR(start_date) = YEAR(CURDATE())
group by MONTH(start_date),
MONTH(end_date)
Use a derived table:
select monstart,
sum(datediff(least(m.monend, t.end_date) + interval 1 day,
greatest(m.monstart, t.start_date)
)
) as days_worked
from travel t join
(select date('2016-01-01') as monstart, date('2016-01-31') as monend union all
select date('2016-02-01') as monstart, date('2016-02-29') as monend union all
. . .
) m
on t.end_date >= m.monstart and t.start_date <= m.monend
group by monstart;

Checking row count based on date range against date range

I'd like to ask you, if there is any way in mysql to do this. I know it can be done by cycle, but feeling like there has to be a better way.
I have table vacation
id | date_from | date_to
1 2017-02-16 2017-02-19
2 2017-02-18 2017-02-21
3 2017-02-12 2017-02-19
4 2017-02-19 2017-02-21
The thing is, that user picks the date range he wants to reserve, like 2017-02-14 to 2017-02-24 and I have to check whether he can still request it, because only 4 people can request vacation simultaneously.
So I need query which will check whether in user selected range (for example 2017-02-14 to 2017-02-24) are for any day 4 or more rows.
Thanks in advance for your answers.
You can do this for any day:
select count(*)
from vacation v
where '2017-02-14' between date_from and date_to;
You can extend this to a range, by specifying each day:
select dte, count(v.id)
from (select date('2017-02-14') as dte union all
select date('2017-02-15') as dte union all
select date('2017-02-16') as dte union all
select date('2017-02-17') as dte union all
select date('2017-02-18') as dte union all
. . .
) d left join
vacation v
on d.dte between date_from and date_to
group by d.dte
having count(*) > 4;
It might be simpler to loop through on the application side. Or, to use a calendar table if you have one.
Select all rows in that date range and count the results:
SELECT count(*) FROM vacation WHERE :input_from BETWEEN date_from AND date_to OR :input_to BETWEEN date_from AND date_to

MySQL Selecting MAX total with date and ID

I have a cron script that writes the total number of active users to a table every day. I'm trying to now generate a simple report that would show the "high water mark" for each month. Because some accounts expire during the month it's possible the highest number may NOT be at the end of the month.
Here's a sample of my table structure
tblUserLog
-----------
record_id INT(11) // PRIMARY KEY
run_date DATE // DATE RUN
ttl_count INT(11) // TOTAL FOR DAY
Sample data:
record_id run_date ttl_count
1 2013-06-01 500
2 2013-06-10 510
3 2013-06-20 520
4 2013-06-30 515
5 2013-07-01 525
6 2013-07-10 530
7 2013-07-20 540
8 2013-07-31 550
9 2013-08-01 560
What I would like returned is:
record_id run_date ttl_count
3 2013-06-20 520
8 2013-07-31 550
9 2013-08-01 560
I've tried two queries that are close...
// This will give me the total for the first of the month
SELECT s.record_id, s.run_date, s.ttl_count
FROM tblStatsIndividual s
JOIN (
SELECT record_id
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
HAVING MAX(ttl_count)
) s2
ON s2.record_id = s.record_id
ORDER BY run_date DESC
This returns the total for the first of each month, along with the record_id and correct date for the total.
Tried this...
SELECT record_id,max(run_date), max(ttl)
FROM (
SELECT record_id,run_date, max(ttl_count) AS ttl
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
) a
GROUP BY DATE_FORMAT(run_date, '%Y %m')
ORDER BY run_date DESC
This one appears to get the correct "high water mark" but it's not returning the record_id, or the run_date for the row that IS the high water mark.
How do you get the record_id and the run_date for the highest total?
Something like
Select detail.Record_ID, detail.Run_Date, detail.ttl_Count
From tblStatsIndividual detail
Inner Join
(Select Year(run_date) as Year, Month(Run_date) as Month, Max(ttl_count) as ttl
From tblStatsIndividual
Group By Year(run_date), Month(Run_date)) maximums
On maximums.Year = Year(detail.Run_date) and maximums.Month = Month(detail.Run_date)
and maximums.ttl = detail.ttl_count
Should do it. NB based on your requirement if you had two records in the same month with the same (and highest in the month) ttl_count, they would both be returned.
Based on the help from #Tony Hopkinson, This query gets me the info. The one caveat is it shows the ID and date for the first occurrence of the MAX total, so if the total is the same three days in a row on a month, the first day's ID is returned. For my purpose, the last ID would be more ideal, but I can live with this:
SELECT s.Record_ID, s.Run_Date, s.ttl_Count
FROM tblStatsIndividual s
INNER JOIN (
SELECT YEAR(run_date) AS yr, MONTH(run_date) AS mon, MAX(ttl_count) AS ttl
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
) maximums
ON maximums.yr = YEAR(s.run_date)
AND maximums.mon = MONTH(s.run_date)
AND maximums.ttl = s.ttl_Count
GROUP BY ttl_count
ORDER BY run_date DESC