SQL Server Detect cumulative sums by group

3pmvbmvn  于 2023-11-16  发布在  其他
关注(0)|答案(1)|浏览(96)

I have a table with distances made by several trucks, I need to detect the time when any of them drove more than 20 miles in less than an hour:

Date    Truck   Dist
05/11/2023 03:12:40 A   9.6
05/11/2023 03:43:25 A   6.5
05/11/2023 04:14:24 A   5.6
05/11/2023 04:43:55 A   7.4
05/11/2023 05:14:10 A   8.7
05/11/2023 05:24:39 A   8.9
05/11/2023 06:41:40 A   12.1
05/11/2023 04:13:33 B   11.5
05/11/2023 04:53:49 B   16.6
05/11/2023 06:14:04 B   7.4
05/11/2023 06:34:19 B   9.2
05/11/2023 07:04:34 B   9.5
05/11/2023 08:24:49 B   0.8

So in this example the return that I want should be:

Date    Truck   Dist
05/11/2023 04:14:24 A   21.7
05/11/2023 05:24:39 A   25
05/11/2023 04:53:49 B   28.1
05/11/2023 07:04:34 B   26.1

I made a macro in Excel that scans row by row and works fine but it takes a lot when I scan thousands of rows and was wondering if there can be a solution in SQL so I can save some time.

For i = 2 To lastrow
        t = i
        cont = Sheets("Data").Range("C" & i)
        Do While Sheets("Data").Range("B" & i) = Sheets("Data").Range("B" & i + 1) And DateDiff("s", Sheets("Data").Range("A" & i).Value, Sheets("Data").Range("A" & t).Value) <= 3600
            cont = cont + Sheets("Data").Range("C" & t)
            t = t + 1
            If cont >= 20 Then
            Sheets("Data").Range("D" & t) = cont
            i = t
            Exit Do
            End If
        Loop
Next
x0fgdtte

x0fgdtte1#

See example.
There used table self join to join every row with all, that starts before current and not not earlier than 1 hour (3600 sec)

with CTE as(
select a.date date_to,a.truck,a.dist,b.date date_from,b.dist dist_from
from test a
left join test b on a.truck=b.truck 
  and datediff(s,b.date,a.date) between 0 and 3600
)
select truck,date_to 
  ,sum(dist_from) rolldist
from CTE
group by truck,date_to
having sum(dist_from)>=20
order by truck,date_to

Subquery (CTE) is "like" your circle "Do While" ;)
For example,part of the results of the subquery before grouping

date_totruckdate_fromdist_fromrolldist
2023-05-11 07:04:34.000B2023-05-11 06:14:04.0007.47.4
2023-05-11 07:04:34.000B2023-05-11 06:34:19.0009.216.6
2023-05-11 07:04:34.000B2023-05-11 07:04:34.0009.526.1

Try Fiddle here

And recursive query for just need to capture a "more than 20 miles" event and then start counting the next one from that row
Example

相关问题