2014-01-23 1 views
1

총 근무 시간이 08:00 이상인 경우 작업 한 총 근무 시간과 초과 근무 시간을 초과하지 않는 경우 초과 근무 시간이 초과 근무 시간을 초과 한 경우 초과 근무 시간 항목에 해당 작업 시간이 표시됩니다. 예 : 적절한 부정적인 형식의 시간 사람이 14:49에서 15:20 시간까지 작업 한 경우 Overtime 열은 -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이 아니기 때문에 (즉,이 시간은 하루에 발생하지 않음)

당신이하려는 것은 시간을 표시하는 데 사용되는 일반적인 형식으로 표시 기간을 표시하는 것입니다. 이것은 시간을 표시하는 것과 동일하지 않습니다. 이것은 단순히 실행하여 공정하게 표시 할 수 있습니다 : 00:00 마이너스 00:31 전날의 23:29 때문에

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

이유가 표시됩니다 이것이다 : 오류가 발생합니다

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

합니다.

저는 개인적으로 모든 계산을 분 단위로 수행합니다.

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 BertrandChoosing the wrong Data Type에 대한 기사에서 이것을 언급한다.그것은 상태 :

기간을

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 

그것은 무의미한 일로, 하루에 각 직원에 대해 하나 이상의 레코드가 있다는 것을 보장합니다. 이는 having 절로 더 잘 수행 될 것입니다. 나 또한 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-서버에서 사용할 수 없습니다. 내 잘못. 그러나이 질문에 걸려 넘어지면 유용 할 수 있으므로 여기에 남겨 두겠습니다.

+1

'서브 타임 '은 MySQL의 기능입니다. SQL Server에는 해당 항목이 없습니다. – GarethD

+0

이 sQlserver에서 작동하지 않습니다. –

+1

@Evilrising 헤어 스플리터가 되려면 : 왜 질문 23 : 00 대신 : "이 아니라"이 작업을 수행하는 올바른 방법을 제공해 주시겠습니까? " ;-) – flu

관련 문제