簡體   English   中英

計算在日期/時間范圍內超出數據集的總時間

[英]Calculating total time that falls outside of dataset within date/time range

我希望為現有應用程序添加一些新功能(數據庫是Microsoft SQL 2005)。 基本上,我正在嘗試計算特定部門在特定日期范圍內“無人”的分鍾數(或秒數)。 我想用一個語句理想地查詢數據集。 我有一個循環記錄集的例程,解析它並吐出答案,但它非常難看。 有沒有人有任何建議我如何優化它的可讀性,使用純SQL - 甚至任何關於我應該看的指針/文章,我的Googlefu讓我失望。

我想在某些方面,這幾乎就像是對日歷的“空閑時間”搜索,但是聚合了。

這是一個模擬樣本數據集,讓您了解我正在使用的內容(有效的同事時鍾,然后退出)。 為了簡單起見,我正在使用四舍五入到下面的分鍾,但我可能會在幾秒鍾內計算。

------------------------------------------------------------------------
| Colleague Id | Department Id   | Date In          | Date Out         |
------------------------------------------------------------------------
| 1            | 1               | 04/01/2010 08:45 | 04/01/2010 11:45 |
| 2            | 1               | 04/01/2010 09:00 | 04/01/2010 12:15 |
| 3            | 1               | 04/01/2010 10:00 | 04/01/2010 12:00 |
| 4            | 1               | 04/01/2010 12:30 | 04/01/2010 17:00 |
| 1            | 1               | 04/01/2010 12:45 | 04/01/2010 17:15 |
| 3            | 1               | 04/01/2010 13:00 | 04/01/2010 17:25 |
| 5            | 2               | ...              | ...              |
------------------------------------------------------------------------

因此,例如,如果我查詢上表中的部門ID = 1,在04/01/2010 08:30:0004/01/2010 17:30:00之間 ,我預計會有35分鍾(或2100)的結果秒 “無人時間”(這是無人值守范圍的開始,中間和結束時間的總和)。

我有一個已經創建的表Integers,我用它來做這樣的事情。

鑒於此,您需要:

drop table foo 
go

create table foo (
   c_id int not null,
   d_id int not null,
   datein datetime not null,
   dateout datetime not null
)
go


insert into foo values (1, 1, '04/01/2010 08:45', '04/01/2010 11:45')
insert into foo values (2, 1, '04/01/2010 09:00', '04/01/2010 12:15')
insert into foo values (3, 1, '04/01/2010 10:00', '04/01/2010 12:00')
insert into foo values (4, 1, '04/01/2010 12:30', '04/01/2010 17:00')
insert into foo values (1, 1, '04/01/2010 12:45', '04/01/2010 17:15')
insert into foo values (3, 1, '04/01/2010 13:00', '04/01/2010 17:25')
go


drop procedure unmanned
go

create procedure unmanned
   @d_id int,
   @start datetime,
   @end datetime

as

select distinct dateadd(ss,i_int,@start)
 from Integers 
      left join foo on dateadd(ss,i_int,@start) >= datein and dateadd(ss,i_int,@start) < dateout


where i_int between 0 and 60*60*24
and dateadd(ss,i_int,@start) >= @start and dateadd(ss,i_int,@start)< @end
and datein is null
order by 1

go

exec unmanned 1, '4/1/10 8:30', '4/1/10 17:30'

這是一個范圍交叉問題:你正在尋找一個數字范圍:

4/01/2010 08:30:00 - 04/01/2010 17:30:00  

此范圍可以表示為數字 - 從一天開始的微秒或秒,例如:

[1000000, 3000000]

並且你想找到它不會與以下任何一個碰撞的部分:

[1200000, 1250000]
[1250000, 1490000]
[1500000, 1950000]
...

當轉換為數字格式時, 它實際上看起來像這個范圍交集算法 ,並且它幾乎可以用任何語言實現。

編輯:

關於日期范圍有一個非常有趣的討論, 這里有很好的插圖和解釋。

我建議使用Eric H的方法。 有了這個免責聲明,這有點令人討厭,但如果由於某種原因無法訪問數字表,它確實提供了做同樣事情的方法。 我確信它可以改進,我只是覺得沒有使用數字表嘗試它:

Declare @Start DateTime, @End DateTime

Select @Start = '04/01/2010 09:30'
    , @End = '04/01/2010 17:30'

--Table Creation Stuff
Declare @y Table (ColleagueId Int, DepartmentId Int, DateIn DateTime, DateOut DateTime)

Insert @y
Select 1, 1, '04/01/2010 08:45' , '04/01/2010 11:45'
Union All Select 2 , 1, '04/01/2010 09:00' , '04/01/2010 12:15'
Union All Select 3 , 1, '04/01/2010 10:00' , '04/01/2010 12:00'
Union All Select 4 , 1, '04/01/2010 12:30' , '04/01/2010 17:00' 
Union All Select 1 , 1, '04/01/2010 12:45' , '04/01/2010 17:15' 
Union All Select 3 , 1, '04/01/2010 13:00' , '04/01/2010 17:25'
---------

Select DateDiff(minute, @Start, @End)  -- TotalTime
     - Sum(DateDiff(minute, 
        Case When DateIn < @Start Then @Start Else DateIn End, 
        Case When DateOut > @End Then @End Else DateOut End)) --StaffedTime
     as UnmannedTime
From
(
    Select Min(din) DateIn, dout DateOut
    From
    (
        Select Min(y.DateIn) din, Max(y2.DateOut) dout
        From @y y
        Inner Join @y y2 on y.DateOut >= y2.DateIn
        --you probably want to close the other end of these filters, but leave some room
        --(to handle the guy who started @ 7:45, etc...)
        Where y.DateIn < @End 
            and y2.DateOut > @Start             
        Group By y.DateIn
    ) x 
    Group By dout
) q

編輯添加了上述案例陳述,以便在特定時期在@Start之前開始(或在@End之后結束)時處理StaffedTime的計算

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM