Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tính toán thời gian thời lượng SQL

Trong một số trường hợp, tôi đã làm điều gì đó tương tự. Về cơ bản, phân nhóm dựa trên sự phân tách trong một trật tự phức tạp. Những điều cơ bản về cách tiếp cận mà tôi sử dụng liên quan đến vấn đề này như sau:

  1. Xây dựng một bảng về mọi phạm vi thời gian được quan tâm.
  2. Tìm thời gian bắt đầu cho từng nhóm phạm vi thời gian được quan tâm.
  3. Tìm thời gian kết thúc cho từng nhóm phạm vi thời gian được quan tâm.
  4. Kết hợp thời gian bắt đầu và kết thúc vào danh sách phạm vi thời gian và nhóm.

Hoặc, chi tiết hơn:(mỗi bước trong số này có thể là một phần của một CTE lớn, nhưng tôi đã chia nhỏ nó thành các bảng tạm thời để dễ đọc ...)

Bước 1:Tìm danh sách tất cả các phạm vi thời gian được quan tâm (tôi đã sử dụng một phương pháp tương tự như phương pháp được liên kết bởi @Brad). LƯU Ý:như @Manfred Sorg đã chỉ ra, điều này giả định rằng không có "giây bị thiếu" nào trong dữ liệu của xe buýt. Nếu có dấu ngắt trong dấu thời gian, mã này sẽ diễn giải phạm vi đơn lẻ là hai (hoặc nhiều) phạm vi riêng biệt.

;with stopSeconds as (
  select BusID, BusStopID, TimeStamp,
         [date] = cast(datediff(dd,0,TimeStamp) as datetime),
         [grp] = dateadd(ss, -row_number() over(partition by BusID order by TimeStamp), TimeStamp)
  from #test
  where BusStopID is not null
)
select BusID, BusStopID, date,
       [sTime] = dateadd(ss,datediff(ss,date,min(TimeStamp)), 0),
       [eTime] = dateadd(ss,datediff(ss,date,max(TimeStamp)), 0),
       [secondsOfStop] = datediff(ss, min(TimeStamp), max(Timestamp)),
       [sOrd] = row_number() over(partition by BusID, BusStopID order by datediff(ss,date,min(TimeStamp))),
       [eOrd] = row_number() over(partition by BusID, BusStopID order by datediff(ss,date,max(TimeStamp)))
into #ranges
from stopSeconds
group by BusID, BusStopID, date, grp

Bước 2:Tìm thời gian sớm nhất cho mỗi điểm dừng

select this.BusID, this.BusStopID, this.sTime minSTime,
       [stopOrder] = row_number() over(partition by this.BusID, this.BusStopID order by this.sTime)
into #starts
from #ranges this
  left join #ranges prev on this.BusID = prev.BusID
                        and this.BusStopID = prev.BusStopID
                        and this.sOrd = prev.sOrd+1
                        and this.sTime between dateadd(mi,-10,prev.sTime) and dateadd(mi,10,prev.sTime)
where prev.BusID is null

Bước 3:Tìm thời gian muộn nhất cho mỗi điểm dừng

select this.BusID, this.BusStopID, this.eTime maxETime,
       [stopOrder] = row_number() over(partition by this.BusID, this.BusStopID order by this.eTime)
into #ends
from #ranges this
  left join #ranges next on this.BusID = next.BusID
                        and this.BusStopID = next.BusStopID
                        and this.eOrd = next.eOrd-1
                        and this.eTime between dateadd(mi,-10,next.eTime) and dateadd(mi,10,next.eTime)
where next.BusID is null

Bước 4:Kết hợp mọi thứ lại với nhau

select r.BusID, r.BusStopID,
       [avgLengthOfStop] = avg(datediff(ss,r.sTime,r.eTime)),
       [earliestStop] = min(r.sTime),
       [latestDepart] = max(r.eTime)
from #starts s
  join #ends e on s.BusID=e.BusID
              and s.BusStopID=e.BusStopID
              and s.stopOrder=e.stopOrder
  join #ranges r on r.BusID=s.BusID
                and r.BusStopID=s.BusStopID
                and r.sTime between s.minSTime and e.maxETime
                and r.eTime between s.minSTime and e.maxETime
group by r.BusID, r.BusStopID, s.stopOrder
having count(distinct r.date) > 1 --filters out the "noise"

Cuối cùng, để hoàn thiện, hãy dọn dẹp:

drop table #ends
drop table #starts
drop table #ranges


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hướng đặt hàng động

  2. Tự động tạo các cột sql

  3. SQL Server 2008 - Thu hẹp Nhật ký Giao dịch - Có cách nào để tự động hóa không?

  4. Tắt các ràng buộc tạm thời (MS SQL)

  5. Tại sao truy vấn này chậm lần đầu tiên sau khi tôi bắt đầu dịch vụ?