2014-01-23 25 views
1

成功計算了一個人的工作總時間和加班時間,如果總工作時間大於08:00,但如果不超過該時間,則人員在超時欄中未工作的時間長度,但現在加班專欄應顯示時間以正確的否定格式表示如果從14:49到 15:20小時工作的人比超時欄應該顯示-00:29,但是我的專欄顯示它是這樣的23:29,爲什麼23:而不是00:?我如何得到正確的時間?時間沒有以適當的格式顯示;額外單位

CODE

with times as (
SELECT t1.EmplID 
     , t3.EmplName 
     , min(t1.RecTime) AS InTime 
     , max(t2.RecTime) AS [TimeOut] 
     , cast(min(t1.RecTime) as datetime) AS InTimeSub 
     , cast(max(t2.RecTime) as datetime) AS TimeOutSub 
     , t1.RecDate AS [DateVisited] 
FROM AtdRecord t1 
INNER JOIN 
     AtdRecord t2 
ON t1.EmplID = t2.EmplID 
AND t1.RecDate = t2.RecDate 
AND t1.RecTime < t2.RecTime 
inner join 
     HrEmployee t3 
ON t3.EmplID = t1.EmplID 
group by 
      t1.EmplID 
     , t3.EmplName 
     , t1.RecDate 
) 
SELECT EmplID 
,EmplName 
,InTime 
,[TimeOut] 
,[DateVisited] 
,convert(char(5),cast([TimeOutSub] - InTimeSub as time), 108) totaltime 
,convert(char(5), case when TimeOutSub - InTimeSub >= '08:01' then 
cast(TimeOutSub - dateadd(hour, 8, InTimeSub) as time) else cast(8 - (TimeOutSub - InTimeSub) as time) end, 108) as overtime 
FROM times 
+1

,如果你使用了一些標點符號和禮貌這將是很好。 – flu

+0

當然,先生,下次會盡我所能:)如你所說:) –

回答

2

那麼原因是因爲數據類型TIME應該存儲時間和-00:29不是一個時間(即這一次將永遠不會發生在一天)。

你要做的是以通常顯示時間的格式顯示顯示時間,這與顯示時間不一樣。這可以被公平地顯示簡單地通過運行:

SELECT CAST('-00:27' AS TIME) 

會拋出錯誤:

Conversion failed when converting date and/or time from character string.

的原因,它顯示這是因爲00:00減去00:31是前一天的23:29

我個人會用分鐘來做所有的計算,例如

SELECT StartTime, 
     EndTime, 
     HoursWorked = DATEDIFF(MINUTE, StartTime, EndTime)/60.0, 
     MinutesOver = 480 - DATEDIFF(MINUTE, StartTime, EndTime) 
FROM (VALUES 
      (CAST('06:50' AS TIME), CAST('15:20' AS TIME)), 
      (CAST('07:50' AS TIME), CAST('15:20' AS TIME)) 
     ) t (StartTime, EndTime); 

其中給出:

StartTime | EndTime | HoursWorked | MinutesOver 
----------+----------+-------------+------------ 
06:50:00 | 15:20:00 |  8.5  | -30 
07:50:00 | 15:20:00 |  7.5  |  30 

然後,您可以在您的表示層應用任何格式。


Aaron Bertrand造成大約Choosing the wrong Data Type的一篇文章中提到這一點。它指出:

使用TIME存儲時間

With SQL Server 2008, it may be tempting to store a duration in a column defined with the new TIME data type. This data type is not meant to store duration but actually a point in time. A problem with trying to store duration here is, what happens when your duration exceeds 24 hours? It would be much more useful to store the "duration" in two columns - StartTime and EndTime. You could add a third column which can be computed, calculating the duration in minutes or seconds or whatever makes sense. Your choice for the StartTime and EndTime columns could be TIME if you are reasonably confident that durations will always be less than 24 hours and will not cross any midnight boundaries, but more likely they should be SMALLDATETIME or DATETIME.


附錄

我將與你的代碼做的第一件事就是取下CTE內內加盟:

FROM AtdRecord t1 
     INNER JOIN AtdRecord t2 
      ON t1.EmplID = t2.EmplID 
      AND t1.RecDate = t2.RecDate 
      AND t1.RecTime < t2.RecTime 

這是毫無意義的,它所做的一切就是確保每位員工每天有多個記錄,而使用條款可以更好地實現這一記錄。我也give your tables meaningful aliases,與2表是不是真的那麼必要,但使用t1,t2,t3等,當你有很多表時會很快混淆。因此,您的查詢就會變成:

WITH Times AS 
( SELECT emp.EmplID, 
      emp.EmplName, 
      InTime = MIN(atd.RecTime), 
      OutTime = MAX(atd.RecTime), 
      TimeWorked = DATEDIFF(MINUTE, MIN(atd.RecTime), MAX(atd.RecTime)), 
      OverTime = DATEDIFF(MINUTE, MIN(atd.RecTime), MAX(atd.RecTime)) - 480, 
      [DateVisited] = atd.RecDate 
    FROM AtdRecord atd 
      INNER JOIN HrEmployee emp 
       ON atd.EmplID = emp.EmplID 
    GROUP BY emp.EmplID, emp.EmplName, atd.RecDate 
    HAVING COUNT(atd.RecTime) > 1 
) 
SELECT t.EmplID, 
     t.EmplName, 
     t.InTime, 
     t.OutTime, 
     t.DateVisited, 
     t.TimeWorked, 
     OverTime, 
     FormattedTimeWorked = CONVERT(CHAR(5), DATEADD(MINUTE, t.TimeWorked, 0), 8), 
     FormattedOverTime = CASE WHEN t.OverTime < 0 THEN '-' ELSE '' END + 
           CONVERT(CHAR(5), DATEADD(MINUTE, ABS(t.OverTime), 0), 8) 
FROM Times t; 

Simplified Example on SQL Fiddle

+0

偉大的先生,令人驚異的,但你能編輯我的代碼顯示想要顯示,我會追加 - 簽名作爲一個字符,但時間? –

+0

atleast會有一種方法來顯示時間一個人沒有工作,這將是有益的,我會追加 - 簽署後 –

+0

你是我的愛先生,令人驚異,愛因斯坦你:) –

0

因爲你減去的日期。

January 14th, 14:49 - January 14th, 15:20January 13th, 23:29。如果你仔細考慮它是有道理的。

使用SUBTIME()代替:

SELECT SUBTIME('14:49', '15:20'); -> '-00:31:00' 

編輯:

SUBTIME()不是SQL-Server中可用。我的錯。但對於任何人在這個問題上磕磕絆絆,這可能是有用的,所以我會把它留在這裏。

+1

'SUBTIME'是一個MySQL函數。在SQL Server中沒有等價物。 – GarethD

+0

不在sQlserver中工作 –

+1

@Evilrising成爲一名髮型師:您的問題是「爲什麼23:而不是00:」,而不是「請您提供正確的方法來做到這一點?」 ;-) – flu

相關問題