SQL Arrange blocks of rows in Order By - mysql

Say I have an original output which looks like this (sorted purely by StartTime):
Name
OrderNo
OpNo
StartTime
Length
A
17345
op10
27/4/22 08:00
04:00:00
B
12727
op 20
27/4/22 11:00
02:00:00
A
18001
op10
27/4/22 13:20
01:00:00
B
17345
op 20
28/4/22 10:17
06:00:00
B
18001
op 20
29/4/22 13:00
04:00:00
C
17345
op 30
3/5/22 16:20
08:00:00
C
18001
op 30
5/5/22 13:00
09:00:00
How would it be possible to order the rows by OrderNo, then by OpNo, and then by the StartTime of the lowest OpNo in each OrderNo? So it would look like this:
Name
OrderNo
OpNo
StartTime
Length
A
17345
op10
27/4/22 08:00
04:00:00
B
17345
op 20
28/4/22 10:17
06:00:00
C
17345
op 30
3/5/22 16:20
08:00:00
B
12727
op 20
27/4/22 11:00
02:00:00
A
18001
op10
27/4/22 13:20
01:00:00
B
18001
op 20
29/4/22 13:00
04:00:00
C
18001
op 30
5/5/22 13:00
09:00:00
I understand it's easy enough to do the Order By OrderNo, OpNo to get the rows sorted into 'blocks' of each OrderNo with asc (or desc) OpNo. But the problem I'm then having is how do I order each of these 'blocks' by the StartTime of the lowest OpNo in each of these 'blocks'?
Hopefully I've made sense?

Using first_value
select *
from (
select *, first_value(StartTime) over(partition by OrderNo order by OpNo) blockStart
from mytable
) t
order by blockStart, OrderNo, OpNo

Related

Time difference without considering times between 0am ~ 4am. MySQL

MySQL version 8.0
I want to calculate time difference between two datetime column.
And get rows where duration >= 12:00:00.
which I would normally do:
select id
, start_time
, end_time
, timediff(end_time, start_time) as duration
from table;
which I would get something like this:
id start_time end_time duration
0 1 2020-06-01 01:00:00 2020-06-01 14:00:00 13:00:00
1 2 2020-06-01 01:00:00 2020-06-01 18:00:00 17:00:00
2 3 2020-06-01 19:00:00 2020-06-02 10:00:00 15:00:00
3 4 2020-06-02 04:00:00 2020-06-02 16:00:00 12:00:00
For duration column I don't want times between 00:00:00 ~ 04:00:00 to be added towards the duration. So for the first row duration = 10:00:00 since 01:00:00~14:00:00 = 10:00:00, ignoring times between 00:00:00 ~ 04:00:00
same for second row we substract 3 hours from duration.
so my desired output would be:
id start_time end_time duration
0 1 2020-06-01 01:00:00 2020-06-01 14:00:00 10:00:00
1 2 2020-06-01 01:00:00 2020-06-01 18:00:00 14:00:00
2 3 2020-06-01 19:00:00 2020-06-02 10:00:00 11:00:00
3 4 2020-06-02 04:00:00 2020-06-02 16:00:00 12:00:00
There are lots of rows where times include minutes and seconds too.
Thanks in advance!
I've grabbed all rows where duration >= 12:00:00.
Then separated data into 4 regions depending on their start_time.
a_region = 00~04
b_region = 04~12
c_region = 12~16
d_region = 16~24
For a_region I've subtracted 04:00:00 - start_time which is time we should compensate to duration in a_region.
compensation = 04:00:00 - start_time
compensated_time = duration - compensation.
For b_region it needs no compensation if it has passed 00~04 it means it already passed duration = 12:00:00.
For c_region,
compensation = 16:00:00 - start_time
compensated_time = duration - compensation
For d_region since we've grabbed duration >= 12:00:00
it will pass all of 00~04 therefore
compensated_time = duration - 04:00:00.
I solved it using Python but above is the logic I've used.
One option uses greatest():
select id
, start_time
, end_time
, timediff(
greatest(,
end_time,
date_format(end_time, '%Y-%m-%d 04:00:00')
),
greatest(
start_time,
date_format(start_time, '%Y-%m-%d 04:00:00')
)
) as duration
from table;

How to find sales per hour between two date

Suppose I have 5 records for a sales table.
ID Name datetime_col
1 ABC 2016-09-15 02:07:56
2 HSJ 2016-09-31 11:45:45
3 JSD 2016-11-26 07:09:56
4 JUH 2016-12-31 12:00:00
5 IGY 2017-01-13 14:00:07
I want to find how many records are there in sales table for each hour between 2016-09-15 AND 2017-01-13
Then result should be like
Hour sales_at_this_hour
2016-09-15 01:00:00 0
2016-09-15 02:00:00 1
2016-09-15 03:00:00 0
...
...
2017-01-13 01:00:00 0
2017-01-13 02:00:00 0
2017-01-13 03:00:00 0
....
2017-01-13 14:00:00 1
Then find the average of sales_at_this_hour using MySQL
EDIT: sorry not fully understand the question at first.
Use DATE_FORMAT
select
DATE_FORMAT(datetime_col, '%Y-%m-%d %h:00:00') as date,
count(id) as count
from table_name
group by date;
Get result with hours that has sales_at_this_hour > 1 (not exactly what you ask for)
datetime_col count
2016-02-04 05:00:00 5
2016-02-04 07:00:00 1
2016-02-04 08:00:00 5
2016-02-04 10:00:00 10
2016-02-04 11:00:00 1
Provide start_date and end_date, and then use DATEDIFF to calculate total time interval for the average calculation.
set #start_date = '2016-01-01', #end_date = '2017-01-01';
select
DATE_FORMAT(group_by_date.datetime, '%h:00:00') as hour,
AVG(group_by_date.count) / DATEDIFF(#end_date, #start_date) as average
from (
select
DATE_FORMAT(created_dtm, '%Y-%m-%d %h:00:00') as datetime,
count(id) as count
from table_name
where created_dtm > #start_date
and created_dtm < #end_date
group by datetime
) group_by_date
group by hour;
For each hour,
average sale count per day = total sale count / total days
hour average
01:00:00 0.03841209
02:00:00 0.01653005
03:00:00 0.0306716
04:00:00 0.01147541
05:00:00 0.01179831

How To Use Distinct Function For Two Column And Sum on PHP MySQL?

I have table like this :
EmployeeID date1 date2 time1 time2 totaltime
12345 2015-09-15 2015-09-15 10:00:00 15:00:00 5
12345 2015-09-15 2015-09-15 08:00:00 09:00:00 1
12345 2015-09-17 2015-09-17 08:00:00 09:00:00 1
12345 2015-09-19 2015-09-19 10:00:00 15:00:00 5
78901 2015-09-30 2015-09-30 10:00:00 15:00:00 5
The problem is i want to distinct the EmployeeID and the date1 coloumn and sum the total time onl for one employeeID who has same date (based on date1). You can see on my example result below :
EmployeeID date1 date2 time1 time2 totaltime
12345 2015-09-15 2015-09-15 10:00:00 15:00:00 5
12345 2015-09-15 2015-09-15 08:00:00 09:00:00 1
so, the result is 6 (5+1).
I have tried to use this syntax :
SELECT DISTINCT (EmployeeID, date1) as totaldate
but nothing happened.
Where is the problem?
And I'm sorry for my bad english.
try this
SELECT EmployeeID, date1, SUM(totaltime) as totaldate
FROM your_table
GROUP BY EmployeeID, date1

How to Group the duplicate items in MySQL separately

I have a request table..
user_id no:of_mach time_start req_time
11 3 2012-12-12 09:00:00 2012-12-11 09:00:00
12 4 2012-12-14 08:00:00 2012-12-14 06:00:00
13 4 2012-12-12 09:00:00 2012-12-12 02:00:00
14 2 2013-12-12 07:00:00 2012-12-12 03:00:00
15 2 2012 12-14 08:00:00 2012-12-14 05:00:00
From the above table, I need to get the req_time of the users who has requested for the same time_start.
The duplicate time_start are
2012-12-12 09:00:00 by user_id 11,13.
2012-12-14 08:00:00 by user_id 12,15.
Now, each of theirs request time is different..
I want a query so that it will get me the result as:-
req_time of user requested for the time_start 2012-12-12 09:00:00 are:-
2012-12-11 09:00:00
2012-12-12 02:00:00
req_time of user requested for the time_start 2012-12-14 08:00:00 are:-
2012-12-14 06:00:00
2012-12-14 05:00:00
I have used a query:-
SELECT req_time FROM user_req WHERE user_id IN (SELECT o.user_id FROM user_req o INNER JOIN ( SELECT starttime, COUNT( * ) AS dupeCount FROM user_req GROUP BY starttime HAVING COUNT( * ) >1)oc ON o.starttime = oc.starttime) ORDER BY req_time ASC;
And this prints all the req_time together for all the duplicate time_start values..
The output will be :-
2012-12-11 09:00:00
2012-12-12 02:00:00
2012-12-14 06:00:00
2012-12-14 05:00:00
Can I have a query that help me to group this req_time based on each duplicate time_start which I have explained above.
Then I can call it in java and use it for my program..
Please help me..
Try this:
select * from user_req where time_start in
(select time_start
from user_req
group by time_start
having count(time_start) > 1)
order by time_start, req_time
This will return records from the table with multiple counts of same time_start, ordered by the start_time and req_time. You can choose to show only those 2 columns if you want by replacing the select * with appropriate column names.

time query for vb6 and msaccess

Query for VB6 and MS Access
Table:-
User Id LogDate LogTime
1 1/1/2010 9:00
1 1/1/2010 10:00
1 1/1/2010 11:29
1 2/1/2010 10:00
2 2/1/2010 22:00
2 3/1/2010 11:00
Need to display as:-
User Id LogDate LogTime LogDate LogTime
1 1/1/2010 9:00 1/1/2010 10:00
1 1/1/2010 11:29 2/1/2010 10:00
2 2/1/2010 22:00 3/1/2010 11:00
You need to use a sub-query to find the next date for a user, something like:
SELECT tblStackOverflowTimeQuery.lngUserId, tblStackOverflowTimeQuery.datLogDateTime,
(SELECT TOP 1 tblStackOverflowTimeQuery2.datLogDateTime
FROM tblStackOverflowTimeQuery AS tblStackOverflowTimeQuery2
WHERE tblStackOverflowTimeQuery.lngUserId = tblStackOverflowTimeQuery2.lngUserId
AND tblStackOverflowTimeQuery2.datLogDateTime > tblStackOverflowTimeQuery.datLogDateTime
ORDER BY tblStackOverflowTimeQuery2.datLogDateTime
) AS datEndDateTime
FROM tblStackOverflowTimeQuery
ORDER BY tblStackOverflowTimeQuery.lngUserId, tblStackOverflowTimeQuery.datLogDateTime;
That'll give the following:
lngUserId datLogDateTime datEndDateTime
1 01/01/2010 09:00:00 01/01/2010 10:00:00
1 01/01/2010 10:00:00 01/01/2010 11:29:00
1 01/01/2010 11:29:00 02/01/2010 10:00:00
1 02/01/2010 10:00:00
2 02/01/2010 22:00:00 03/01/2010 11:00:00
2 03/01/2010 11:00:00
which is not exactly what you wanted, but it's a start.
It would be easiest to do these things using code, but that would depend on how you want to use it. Presumably there's nothing in your data to indicate which entry is the start and which is the end.