計算兩個時間相差幾小時幾分幾秒

本文將介紹如何利用 T-SQL 計算兩個時間相差幾小時幾分幾秒。

論壇上看到有網友問到要計算員工的遲到早退的問題,看起來不是很難但一下子腦筋轉不過來,筆者 TRY 了好久又沒想到要去問 GOOGLE 大神,硬擠出下列的笨方法來湊出結果。

 

   1:  use master
   2:  go
   3:   
   4:  declare @t1 table
   5:  (Y char(4)
   6:  ,M varchar(2)
   7:  ,D  varchar(2)
   8:  ,H  char(2)
   9:  ,Mi char(2)
  10:  ,S char(2)
  11:  ,cardno char(2)
  12:  ,name char(1)
  13:  )
  14:   
  15:  insert into @t1 values 
  16:  ('2012',     '2',     '1',      '07',    '08',   '40',     '01',          'A')
  17:  ,('2012',     '2',     '1',      '07',    '09',   '40',     '02',          'B')
  18:  ,('2012',     '2',     '1',      '07',    '08',   '45',     '01',          'A')
  19:  ,('2012',     '2',     '1',      '07',    '09',   '50',     '02',          'B')
  20:  ,('2012',     '2',     '1',      '08',    '10',   '45',     '03',          'C')
  21:  ,('2012',     '2',     '1',      '08',    '08',   '40',     '03',          'C')
  22:  --以下為計算是否早退所用的測試資料
  23:  ,('2012',     '2',     '1',      '17',    '08',   '45',     '01',          'A')
  24:  ,('2012',     '2',     '1',      '16',    '09',   '50',     '02',          'B')
  25:  ,('2012',     '2',     '1',      '15',    '15',   '45',     '03',          'C')
  26:   
  27:  select dd
  28:  ,MIN(tt) as intime --簽到時間
  29:  ,MAX(tt) as outime --簽退時間
  30:  ,cardno,name
  31:  ,case when MIN(tt) > '08:00:00' and MIN(tt) < '17:00' then DATEADD(HH,-8,MIN(tt)) 
  32:   else null end as late --遲到時間
  33:  ,case when MAX(tt) < '17:00' then 
  34:  CONVERT(varchar,DATEDIFF(HOUR,MAX(tt),'17:00:00')-1)
  35:  + ':' 
  36:  + CONVERT(varchar,60-(DATEPART(MINUTE,MAX(tt))))
  37:  + ':' 
  38:  + CONVERT(varchar,60-(DATEPART(SECOND,MAX(tt))))
  39:   else null end as early --早退時間
  40:  from 
  41:  (
  42:  select CONVERT(date,Y+RIGHT('0' + M,2)+RIGHT('0' + D,2)) as dd
  43:  ,CONVERT(time,H+':' +Mi+':' + S) as tt
  44:  ,cardno,name
  45:  from @t1 t1
  46:  ) t1
  47:  group by dd,cardno,name

 

 

後來跟 Rainmaker 大討論,原來可以利用 CONVERT 函數來轉型,搭配 108 這個 style 就可以精簡的做出計算兩個時間相差幾小時幾分幾秒了,程式碼修正如下:

 

   1:  use master
   2:  go
   3:   
   4:  declare @t1 table
   5:  (Y char(4)
   6:  ,M varchar(2)
   7:  ,D  varchar(2)
   8:  ,H  char(2)
   9:  ,Mi char(2)
  10:  ,S char(2)
  11:  ,cardno char(2)
  12:  ,name char(1)
  13:  )
  14:   
  15:  insert into @t1 values 
  16:  ('2012',     '2',     '1',      '07',    '08',   '40',     '01',          'A')
  17:  ,('2012',     '2',     '1',      '07',    '09',   '40',     '02',          'B')
  18:  ,('2012',     '2',     '1',      '07',    '08',   '45',     '01',          'A')
  19:  ,('2012',     '2',     '1',      '07',    '09',   '50',     '02',          'B')
  20:  ,('2012',     '2',     '1',      '08',    '10',   '45',     '03',          'C')
  21:  ,('2012',     '2',     '1',      '08',    '08',   '40',     '03',          'C')
  22:  --以下為計算是否早退所用的測試資料
  23:  ,('2012',     '2',     '1',      '17',    '08',   '45',     '01',          'A')
  24:  ,('2012',     '2',     '1',      '16',    '09',   '50',     '02',          'B')
  25:  ,('2012',     '2',     '1',      '15',    '15',   '45',     '03',          'C')
  26:   
  27:  select dd
  28:  ,MIN(tt) as intime --簽到時間
  29:  ,MAX(tt) as outime --簽退時間
  30:  ,cardno,name
  31:  ,case when MIN(tt) > '08:00:00' and MIN(tt) < '17:00' 
  32:          then CONVERT(varchar, DATEADD(s, DATEDIFF(s,'08:00:00',MIN(tt)), 0), 108)
  33:   else null end as late --遲到時間
  34:  ,case when MAX(tt) < '17:00' 
  35:          then CONVERT(varchar, DATEADD(s, DATEDIFF(s,MAX(tt),'17:00:00'), 0), 108)
  36:   else null end as early --早退時間
  37:  from 
  38:  (
  39:  select CONVERT(date,Y+RIGHT('0' + M,2)+RIGHT('0' + D,2)) as dd
  40:  ,CONVERT(time,H+':' +Mi+':' + S) as tt
  41:  ,cardno,name
  42:  from @t1 t1
  43:  ) t1
  44:  group by dd,cardno,name

執行結果如下:

 

image

 

【參考資料】