2015-10-09 47 views
2

我有ViewSQL名稱爲vw_Rept_Attend和列名在HH返回大於24小時:mm:ss格式在SQL Server 2008

UserID (int),WorkHrs (varchar),ExtraHrs varchar(), AtnDate (datetime), EmpName (varchar), 
EmpType (varchar), UserName (varchar),Role (varchar) 

WorkHrs實際工作和ExtraHrs

等什麼我這樣做是

我存儲在WorkHrs員工的每日工作時間和ExtraHrs額外的小時,然後我顯示出席總結通過過濾器提供的兩個日期之間RY報告,

很明顯,我做的最大的事情與你的專家建議,申請將小數據和客戶端的測試工作正常,我得到了我沒有在那個時候考慮的一個問題

問題描述

每一個員工都有工件9小時,每天(每天工作時間)

工作時間(登錄時間)

加班(每天工作時間 - 工作時間)

如果員工工作6 hours所以他額外的時間將是-3 hours負的,因爲少工作時間比需要的時間和我這個c#聲明

wrktime= workinghrs.Subtract(Convert.ToDateTime(time).TimeOfDay); 
TimeSpan Daily_work = new TimeSpan(9, 0, 0); 
TimeSpan exthrs = Convert.ToDateTime(wrktime).TimeOfDay.Subtract(Daily_work); 
得到這個結果

,這會給我負當任何一個工作少於9 hours

因此,如果用戶對300 days每天-3 hours添加到database結果將是這樣做爲300 days

我閱讀使用以下sqlprocedure對水晶報表

ALTER PROCEDURE [dbo].[sp_Rpt_Emps_Attnd] 
    @strt date, 
    @end date 
AS 

    begin 
    with cte 
as 
(select UserID, 
      WorkHrs, 
     case when left(ExtraHrs,1)='-' then -1 else 1 end as multiply, 
      right(ExtraHrs,8) as timestring, 
      --get hours in seconds: 
      DATEPART(HOUR,right(ExtraHrs,8)) * 3600 AS h_in_s, 
      --get minutes in seconds: 
      DATEPART(MINUTE,right(ExtraHrs,8)) * 60 AS m_in_s, 
      --get seconds: 
      DATEPART(SECOND,right(ExtraHrs,8)) AS s,AtnDate,EmpName,EmpType, 
      UserName, Role,StartDate,EndDate 

    from  vw_Rept_Attend 
) 

select UserID,dbo.udfTimeSpanFromSeconds(Sum(Left(workhrs,2) * 3600 + substring(Convert(varchar(8),workhrs), 4,2) * 60 + substring(Convert(varchar(8),workhrs), 7,2))) as WorkHrs , 
case when sum((c.h_in_s + c.m_in_s + c.s) * multiply) < 0 
      then '-' + CONVERT(varchar,DATEADD(s,ABS(sum((c.h_in_s + c.m_in_s + c.s) * multiply)),0),114) 

      else CONVERT(varchar,DATEADD(s,sum((c.h_in_s + c.m_in_s + c.s) * multiply),0),114) 
     end as ExtraHrs ,EmpName,EmpType,UserName, Role,convert(VARCHAR(10),StartDate,105) as StartDate,convert(VARCHAR(10),EndDate,105) as EndDate 

from cte c where convert(date,AtnDate) between @strt and @end 
group by UserID,EmpName,EmpType,UserName, Role,StartDate,EndDate 
    Order by UserID 
    end 

和功能顯示的計算日期之間的所有WorkHrs的總和作爲

ALTER FUNCTION udfTimeSpanFromSeconds(
     @sec INT 
    ) 
    RETURNS VARCHAR(15) 
    AS 
    BEGIN 

RETURN 
    CONVERT(VARCHAR(10), (@sec/3600)) + ':' + 
    RIGHT('0' + CONVERT(VARCHAR(2), ((@sec % 3600)/60)), 2) + ':' + 
    RIGHT('0' + CONVERT(VARCHAR(2), (@sec % 60)), 2) 
END 

我是從把所有這個紀錄我stackHow to format time from dd:hh:mm:ss to only hh:mm:ss in SQL server?

但是th這是stored procedure一部分我提到上面即

case when left(ExtraHrs,1)='-' then -1 else 1 end as multiply, 
      right(ExtraHrs,8) as timestring, 
      --get hours in seconds: 
      DATEPART(HOUR,right(ExtraHrs,8)) * 3600 AS h_in_s, 
      --get minutes in seconds: 
      DATEPART(MINUTE,right(ExtraHrs,8)) * 60 AS m_in_s, 
      --get seconds: 
      DATEPART(SECOND,right(ExtraHrs,8)) AS s 

計算ExtHrs總和電子部分只支持24 hours例如,如果結果是27 hours然後它顯示3 hours,如果它是-56 hours然後它顯示-8 hours

我使用SQL Server 2008,

我認爲足夠的描述來理解,但如果你們中的任何人不明白,那麼請免費要求我分享代碼或我使用的任何邏輯。

您的幫助將不勝感激,

在此先感謝。

編輯:

這個問題What is the correct SQL type to store a .Net Timespan with values > 24:00:00?是完全不同的,因爲我不是問哪個datatype我應該使用

這裏的應用程序可以獲取負時間值,例如,-3小時,我說得很清楚,並timespan數據類型不接受負號。

現在我覺得應該清除

更新 在我的數據庫,它看起來像

enter image description here

這樣計算後ExtHrs應該是-31:50:46但它顯示-7:50:46

我認爲這是因爲不支持大於24 hours

+0

你能拋出一些樣本數據,比如只有Extrahr和workhr數據以及你期望的輸出嗎? – KumarHarsh

+0

@KumarHarsh,請參閱我的編輯 – Waqas

回答

1

順便說一句,在你使用的proc以及數據類型中有太多的技術缺陷。真正的問題在這裏。

  1. 在你的proc中,你可以把第一個CTE本身的日期條件放在哪裏。
  2. 如果可能的話,你可以在第二個表格中存儲extrahour。這意味着Extrahours是int或者bigint.like -1000或者1000.varchar永遠不會解決你的問題。它會以很快的速度爲你節省很多轉換。
  3. 在組中使用如此之多的列本身是錯誤的方法,特別是在組中使用varchar列。您應該使用組中的鍵列,然後再與表連接以獲得結果集中的其他列。

與您的示例數據我得到-29:-51:-30.0而不是-31:50:46。 做這種方式,

DECLARE @t TABLE (ExtraHrs VARCHAR(20)) 

INSERT INTO @t 
VALUES ('00:59:38') 
    ,('-03:59:37') 
    ,('-08:59:39') 
    ,('-08:52:36') 
    ,('-08:59:16'); 

WITH cte 
AS (
    SELECT ExtraHrs 
     ,CASE 
      WHEN left(ExtraHrs, 1) = '-' 
       THEN - 1 
      ELSE 1 
      END AS multiply 
     ,right(ExtraHrs, 8) AS timestring 
     , 
     --get hours in seconds: 
     DATEPART(HOUR, right(ExtraHrs, 8)) * 3600 AS h_in_s 
     , 
     --get minutes in seconds: 
     DATEPART(MINUTE, right(ExtraHrs, 8)) * 60 AS m_in_s 
     , 
     --get seconds: 
     DATEPART(SECOND, right(ExtraHrs, 8)) AS s 
    FROM @t 
    ) 
    ,CTE3 
AS (
    SELECT * 
     ,c.h_in_s + c.m_in_s + c.s AddExtra 
    FROM cte c 
    ) 
    ,cte4 
AS (
    SELECT sum(AddExtra * multiply) mn 
    FROM cte3 
    ) 
    ,cte5 
AS (
    SELECT mn/3600 hh 
     ,(mn % 3600)/60 mi 
     ,(mn % 3600.0) % 60 ss 
    FROM cte4 
    ) 
SELECT CASE 
     WHEN hh < 0 
      THEN '-' 
     ELSE '' 
     END 
    ,cast(hh AS VARCHAR) + ':' + cast(mi AS VARCHAR) + ':' + cast(ss AS VARCHAR) 
FROM cte5 

嘗試此前導零,

申報@i INT = 5 SELECT REPLICATE( '0',2-LEN(@i))+鑄(@i as varchar)

+0

我需要一些時間瞭解和實施這一點,然後我會更新你,感謝您的時間和精力, – Waqas

+0

其工作正常,但有點問題,我得到「-2:37:12」爲「-2:-37:-12.0」,它應該只有「-02:37:12」格式不能與分鐘和秒, – Waqas

+0

給我時間。所以只有格式化是一個問題?好 ?也不要使用如此多的cte,因爲我有使用。那麼多不需要。我糾正格式併發布。 – KumarHarsh

0

ExtraHrs是一個字符串。所以是right(ExtraHrs,8)。那麼如何使用日期時間函數(即DATEPART)呢?你不應該這樣做。

現在使用什麼格式ExtraHrs?你似乎期望有一個可選的(?)符號,後面跟着hh:mm:ss的8個字符。

隨着字符串函數和強制轉換爲數字小值,你會得到:

case when left(extrahrs, 1) = '-' then -1 else 1 end * -- sign 
( 
    (cast(substring(right(extrahrs, 8), 1, 2) as int) * 3600) + -- hours 
    (cast(substring(right(extrahrs, 8), 4, 2) as int) * 60) + -- minutes 
    (cast(substring(right(extrahrs, 8), 7, 2) as int)) + -- seconds 
) as secs 

這使得時間跨度達將近100小時。對於更多的小時,您的格式將不得不更改爲hhh:mm:ss或甚至可變長度。

+0

感謝您的關注,先生,SQL不允許我更新過程並拋出「substr不是公認的內置函數名稱」的錯誤任何建議,? – Waqas

+0

嗨瓦卡斯。將其更改爲SUBSTRING而不是substr。我編輯了答案,但我正在等待它被同行評審 – TheDanMan

+0

@TheDanMan:謝謝。 –

相關問題