Group based on time difference between two date values - sql

I've searched around, but haven't been able to find anyone else with this same question.
I'm working with SQL Server (2008 R2).
Let's say I have the following three rows of data coming back from my query. What I need to do is group the first two rows into one (in either SQL Server or SSRS) based on the difference in minutes between the Start Time and the End Time (the Duration). How much time elapses between one row's End Time and the next row's Start Time is of no concern; I'm only looking at Duration.
Current result set:
+---------+------------+------------+----------+
| Vehicle | Start Time | End Time | Duration |
+---------+------------+------------+----------+
| 12 | 1:56:30 AM | 2:07:47 AM | 11 |
+---------+------------+------------+----------+
| 12 | 2:07:57 AM | 6:46:08 AM | 279 |
+---------+------------+------------+----------+
| 19 | 2:55:02 PM | 3:45:59 PM | 53 |
+---------+------------+------------+----------+
Desired result set:
+---------+------------+------------+----------+
| Vehicle | Start Time | End Time | Duration |
+---------+------------+------------+----------+
| 12 | 1:56:30 AM | 6:46:08 AM | 290 |
+---------+------------+------------+----------+
| 19 | 2:55:02 PM | 3:45:59 PM | 53 |
+---------+------------+------------+----------+
I feel like it has to be a matter of grouping, but I'm not sure how to group based on whether or not the start and end times are less than 15 minutes apart.
How can this be accomplished?

Unless I misunderstood your question, try this
Select Vehicle
,StartTime = min(StartTime)
.EndTime = max(EndTime)
,Duration = sum(Duration)
From YourTable
Group By Vehicle

Related

MS Access: show count per hour (even if there are no records in the time slot)

I'm stuck, i think it should be simple but can't get it to work. I have a table 'tbTimeTable' with all the hours of the day.
tbTimeTable (only show the first 5 records, but it will end at 23:00 (24 records in total)
| ID | TimeStart | TimeStop |
|1 | 0:00 | 1:00 |
|2 | 1:00 | 2:00 |
|3 | 2:00 | 3:00 |
|4 | 3:00 | 4:00 |
|5 | 4:00 | 5:00 |
I have a totals query qryPartCountTotalsPerHour with the part count per hour.
| DateIn | PartCount | PeriodIn | PerdiodOut |
|19-5-2021 | 221 |0:00 | 1:00 |
|19-5-2021 | 203 |1:00 | 2:00 |
|19-5-2021 | 201 |2:00 | 3:00 |
|19-5-2021 | 215 |6:00 | 7:00 |
|19-5-2021 | 174 |7:00 | 8:00 |
What I want, is to show the part count result for all the hours of the day and if there are no records in that hour then show 0 in the part count. So every Date in the DateIn field should show at least 24 records.
I tried this:
SELECT qryPartCountTotalsPerHour.DateIn, qryPartCountTotalsPerHour.PartCount, qryPartCountTotalsPerHour.PeriodOut, qryPartCountTotalsPerHour.PeriodOut
FROM tbTimeTable LEFT JOIN qryPartCountTotalsPerHour ON tbTimeTable.TimeStart = qryPartCountTotalsPerHour.PeriodIn
ORDER BY qryPartCountTotalsPerHour.DateIn;
I also tried to convert the PeriodIn and TimeStart just to an 'Hour' with the Hour() function but nothing works. I make mistake somewhere but can't find it.
Edit: tried to clarify that the DateIn contains more than one date.
You are close. You need to aggregate by the first table:
SELECT t.PeriodIn, NZ(q.PartCount), q.PeriodOut, q.PeriodOut
FROM tbTimeTable as t LEFT JOIN
qryPartCountTotalsPerHour as q
ON t.TimeStart = qryPqrtCountTotalsPerHour.PeriodIn
ORDER BY t.PeriodIn;
This works for your sample data. It might get more complicated if more days are involved.
So I found the answer. This topic helped me to get the answer, specifically the answer from Ken Sheridan and his public database "Payments". This database should give you enough info to solve this or a similair problem. However I will give you a short brief of what I did.
So I created a query with the time table and all the log dates (no relationship between them) called qryCalendar. This resulted in the complete time table for each logging date.
Then I created a new query to show the final result:
SELECT qryCalendar.Date, qryCalendar.TimeStop, qryCalendar.TimeStart, Nz([qryPartCountTotalsPerHour].[PartCount],0) AS tPartCount
FROM qryCalendar LEFT JOIN qryPartCountTotalsPerHour ON (qryCalendar.TimeStop = qryPartCountTotalsPerHour.PeriodOut) AND (qryCalendar.Date = qryPartCountTotalsPerHour.DateIn)
ORDER BY qryCalendar.Date, qryCalendar.TimeStart;

ORACLE SQL query to get rows of intervals of 30 minutes based on two hours

I need to do a query that give me rows of 30 minutes of intervals based on two hours, start_hour and end_hour.
I have a table, in this table i have this columns "start_hour and end_hour".
Assuming that i have this
| start_hour | end_hour |
| 09:00AM | 08:00PM |
I need a query that gave a result like this.
| intervals |
| 09:00AM |
| 09:30AM |
| 10:00AM |
| 10:30AM |
| 11:00AM |
| 11:30AM |
| 12:00AM |
| 12:30AM |
...
...
...
| 07:30PM |
| 08:00PM |
And the rows need to finish in te end_hour value i have in the table, as shown in the example.
Someone can help me how to do it, i tried rounding the start_hour, but i don't have any result.
This is a bit clunky and will take a bit of editing based on your specific needs, but it's a very slightly modified bit of code I used a few years back that should work as a solid starting point for you:
select to_char(time_slot,'HH:MIPM')
from (select trunc(to_date('05/23/2019','MM/DD/YYYY'))+(rownum-1)*(30/24/60) time_slot
from dual
connect by level <= (24*2))
where to_char(time_slot,'HH24:MI') between
--start_hour
'09:00'
and
--end hour
'20:00';
OUTPUT
09:00AM
09:30AM
10:00AM
10:30AM
11:00AM
11:30AM
12:00PM
12:30PM
01:00PM
01:30PM
02:00PM
02:30PM
03:00PM
03:30PM
04:00PM
04:30PM
05:00PM
05:30PM
06:00PM
06:30PM
07:00PM
07:30PM
08:00PM

PostgreSQL query and data caching

I have this SQL query:
SELECT p.timestamp,
COUNT(*) as total,
date_part('hour', p.timestamp) as hour
FROM parties as p
WHERE p.timestamp >= TIMESTAMP 'today' AND p.timestamp < TIMESTAMP 'tomorrow'
AND p.member_id = 1
GROUP BY p.timestamp, hour;
which will grouped how many people by hour:
+-------------------------+-------+------+
| Timestamp | Total | Hour |
+-------------------------+-------+------+
| 2018-11-21 12:00:00+07 | 10 | 12 |
| 2018-11-21 13:00:00+07 | 2 | 13 |
| 2018-11-21 14:00:00+07 | 2 | 14 |
| 2018-11-21 16:00:00+07 | 1 | 16 |
| 2018-11-21 17:00:00+07 | 21 | 17 |
| 2018-11-21 19:00:00+07 | 18 | 19 |
| 2018-11-21 20:00:00+07 | 8 | 20 |
| 2018-11-21 21:00:00+07 | 1 | 21 |
+-------------------------+-------+------+
My question is, if I refetch some API end point that will query above statement, would it be the data in the past hour cached automatically? because in my case, if there is a new data, it will update the last hour's row only.
If not how to cache it? Thanks in advance
PSQL can not cache result of query itself. The solution is cache the result at API application layer.
I prefer using redis to cache it. Using a hash with fields is year+month+day+hour and value is total online user of each hour. Example:
hash: useronline
field: 2018112112 - value: 10
field: 2018112113 - value: 2
You also set a timeout on key. After the timeout has expired, the key will automatically be deleted. I will set 1 hour in here.
EXPIRE useronline 3600
When have API request we will get result in redis cache first. If do not exist or expired call query to database layer to get result, save to redis cache again. Reponse result to client.
Here is list of redis clients suitable for programing language.

Finding the max value between the last 22 months or between any 10 hour window within the last 22 months in Microsoft SQL Server

I'd like to find the max value within the last 22 months OR the max value within any 10 hour window of those last 22 months.
I'm doing this in Microsoft SQL Server.
Essentially, I'm looking to retrieve a value that has sustained a high for at least 10 hours before I consider it my max and if it is larger than the max of the last 22 months, it would be the new max, otherwise I would use the max of the last 22 months.
Here's what I think it should look like pseudo code:
if (time > 10 hours) AND (value = max) OR (18 > time > 0) AND (value = max)
then output = value
The SQL code that I've tried:
SELECT TOP 90 PERCENT
DATEADD(s,time,'19700101') as time_22month
,GETDATE() as date_22month
,b.tagname as tag_22month
,value as value_22month
,maximum as max_22month
FROM
db..hour a
INNER JOIN
db..tag b
ON
a.tagid = b.tagid
WHERE
b.tagname like '%T500.1234%'
AND
(GETDATE() - DATEADD(s, time, '19700101') < 670)
ORDER BY
max_22month DESC
SELECT
DATEADD(s,time,'19700101') as time_10hour
,GETDATE() as date_10hour
,b.tagname as tag_10hour
,value as value_10hour
,maximum as max_10hour
FROM
db..hour a
INNER JOIN
db..tag b
ON
a.tagid = b.tagid
WHERE
b.tagname like '%T500.1234%'
AND
(GETDATE() - DATEADD(s, time, '19700101') < 0.42)
ORDER BY
max_10hour DESC
Output right now is the following:
+-------------------------+----------------------------+-------------+----------------+---------------+
| time_22month | date_22month | tag_22month | value_22month | max_22month |
+-------------------------+----------------------------+-------------+----------------+---------------+
| 2016-03-08 06:00:00.000 | 2017-04-10 10:07:57:32.783 | T500.1234 | 1567.88546416 | 2445.56419848 |
| 2016-03-08 07:00:00.000 | 2017-04-10 10:07:57:32.783 | T500.1234 | 1499.88546416 | 2434.47673719 |
+-------------------------+----------------------------+-------------+----------------+---------------+
+-------------------------+----------------------------+------------+---------------+---------------+
| time_10hour | date_10hour | tag_10hour | value_10hour | max_10hour |
+-------------------------+----------------------------+------------+---------------+---------------+
| 2017-04-10 00:00:00.000 | 2017-04-10 10:07:57:32.783 | T500.1234 | 8763.42572454 | 8759.64548912 |
| 2017-04-10 01:00:00.000 | 2017-04-10 10:07:57:32.783 | T500.1234 | 8001.64578943 | 8001.64578943 |
+-------------------------+----------------------------+------------+---------------+---------------+
So I'm a little confused on how I should be comparing these max values, especially when the 10 hour window needs to be rolling (incrementing every hour). Any help is appreciated.
The output should be the greater value of the two parameters, so perhaps a new table column would be the output along with two columns that precede it that show the highest 22month value and the highest 10 hour window value.
+--------+-------------+------------+------+
| Month | 22Month_Max | 10Hour_Max | Max |
+--------+-------------+------------+------+
| July | 5478 | 5999 | 5999 |
| August | 4991 | 3523 | 4991 |
+--------+-------------+------------+------+

SQL -- Derive Date Difference Column

+------+-------------------------+
| proc | endTime |
+------+-------------------------+
| A | 2010/01/01 12:10:00.000 |
| B | 2010/01/01 12:08:00.000 |
| C | 2010/01/01 12:05:00.000 |
| D | 2010/01/01 12:02:00.000 |
| ...| ... |
So basically the data I pull from the database will look something like the above, with the first column being the name of a process, and the second column the time it finished running. I want to add a THIRD column, where it displays the running time of the process.
Basically, I want the data pulled to look like this instead:
+------+-------------------------+--------------+
| proc | endTime | runningTime |
+------+-------------------------+--------------+
| A | 2010/01/01 12:10:00.000 | | (process a is not done running)
| B | 2010/01/01 12:08:00.000 | 00:03:00.000 |
| C | 2010/01/01 12:05:00.000 | 00:03:00.000 |
| D | 2010/01/01 12:02:00.000 | 00:02:00.000 | (assume 12:00 start time)
| ...| ... | ... |
And I know it would be easier it add a startTime column and from that determine runningTime, but I don't have access to change that, and regardless the old data would not have a startTime to work with anyways.
The first process's start time is arbitrary, but you see what I'm getting at. We know the run time of proc C based on when proc D ended, and the when proc C ended (subtract the first from the second).
How do I compute that third row based on the difference between "Row X Col B" and "Row X-1 Col B"?
I don't think you can add it as a "calculated column". You can calculate it in a view pretty easily like this (all code for MSSQL. Your convert function may vary):
select
e1.RowID,
e2.EndTime as StartTime,
e1.EndTime, runningtime=convert(varchar(20), e1.EndTime - e2.EndTime, 114)
from endtimetest e1
left join endtimetest e2 on e2.endtime =
(Select max(endtime)
from endtimetest
where endtime < e1.Endtime)
Or, you could calculate it in a trigger with something similar.