那麼原因是因爲數據類型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
,如果你使用了一些標點符號和禮貌這將是很好。 – flu
當然,先生,下次會盡我所能:)如你所說:) –