2011-11-29 27 views
2

將登錄日期時間與單一表中的註銷日期時間配對,並計算工作時間。配對登錄和註銷日期時間,並計算工作時間

EmployeeLogInOut表:

TransactionID bigint, 
TransactionDate datetime, 
Type smallint, 
Automatic bit, 
SalesDate datetime, 
EmployeeGUID uniqueidentifier, 
DepartmentGUID uniqueidentifier 

見下面的sampleData。

類型:1 =登錄2 =註銷

自動:0 =手動1 =自動

自動occure當員工不要在一天結束時註銷。如果他/她沒有註銷,系統將在日結束時註銷員工aoyomaticaly。

也有可能是,當軟件更新occure等的員工可以atomaticaly註銷...

對於repport我需要計算多少分鐘的員工已經在該系統在每天登錄(SalesDate)。

我試圖讓我的結果成表像

LogOnTime datetime, 
LogOffTime datetime, 
DurationInMinute int, 
DepartmentGUID uniqueidentifier 

但因爲有可能不存在,每個登錄,反之亦然一個相應的退出,我對這種做法得到一個錯誤。

我的腳本:

declare @EmployeeGUID uniqueidentifier 
declare @StartDate datetime 
declare @EndDate datetime 

set @EmployeeGUID = 'C335F76A-E757-48D9-8DFE-01096EEA6A71' 
set @StartDate = '09-01-2011' 
set @EndDate = '09-30-2011' 



create table #result 
(
    LogOnTime datetime, 
    LogOffTime datetime, 
    DurationInMinute int, 
    DepartmentGUID uniqueidentifier 
) 


    Insert #result(LogOnTime,LogOffTime,DurationInMinute,DepartmentGUID ) 
    Select A.TransactionDate, B.TransactionDate,datediff(minute,A.TransactionDate, isnull(B.TransactionDate,GetDate())),A.DepartmentGUID 
     from 
     (Select Row_number() over (order by TransactionDate) as Num ,* from EmployeeLogInOut 
     where [Type]=1 and EmployeeGUID = @EmployeeGUID and SalesDate between @StartDate and @EndDate) as A 
     LEFT JOIN 
     (Select Row_number() over (order by TransactionDate) as Num,* from EmployeeLogInOut 
     where [Type]=2 and EmployeeGUID = @EmployeeGUID and SalesDate between @StartDate and @EndDate) as B 
     ON A.Num = B.Num 

    select * from #result 
    drop table #result 

的樣本數據:

CREATE TABLE EmployeeLogInOut(
    [TransactionID] [bigint] NOT NULL, 
    [TransactionDate] [datetime] NOT NULL, 
    [Type] [smallint] NOT NULL, 
    [Automatic] [bit] NOT NULL, 
    [SalesDate] [datetime] NOT NULL, 
    [EmployeeGUID] [uniqueidentifier] NOT NULL, 
    [DepartmentGUID] [uniqueidentifier] NOT NULL 
) 

INSERT INTO EmployeeLogInOut VALUES 
(2006,'2011-09-05 16:59:39.000',1,0,'2011-09-05 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2008,'2011-09-05 21:57:22.000',2,0,'2011-09-05 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2019,'2011-09-06 16:59:37.000',1,0,'2011-09-06 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2022,'2011-09-06 17:35:41.430',2,0,'2011-09-06 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2039,'2011-09-06 17:36:41.000',2,1,'2011-09-06 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2023,'2011-09-06 17:37:41.000',1,0,'2011-09-06 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2037,'2011-09-07 00:45:32.000',2,0,'2011-09-06 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2054,'2011-09-08 17:12:19.000',1,0,'2011-09-08 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2059,'2011-09-08 20:58:17.000',2,0,'2011-09-08 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2262,'2011-09-20 20:09:10.000',1,0,'2011-09-20 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2269,'2011-09-21 06:59:00.000',2,1,'2011-09-20 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2278,'2011-09-21 17:06:49.000',1,0,'2011-09-21 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2282,'2011-09-21 22:05:29.000',2,0,'2011-09-21 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2283,'2011-09-21 22:06:55.000',1,0,'2011-09-21 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A'), 
(2284,'2011-09-21 22:09:04.000',2,0,'2011-09-21 00:00:00.000','C335F76A-E757-48D9-8DFE-01096EEA6A71','520EEFD4-DC30-4390-BB7F-FEFD83D9576A') 

任何想法,將不勝感激:-)

我的想法是,如果相應的登錄日期時間不存在對LogOut時間,則相應的LogIn日期時間可以設置爲06:00,在實際的salesDate上。

如果登錄日期時間缺少相應的註銷日期時間它可以被設置爲05:59

,或者直接忽略不對應所有登錄/註銷enteries。

PS:我無法更改EmployeeLogInOut表格,也無法將數據輸入到表格中。

+0

這真的取決於用戶的要求是什麼。他們是否在乎你是否忽略了沒有登錄/退出時間的記錄?如果沒有,那麼他們應該能夠指定應該如何處理丟失的日期時間。一旦你知道了,我們可以製作一些SQL來匹配需求。 – Bert

+0

感謝您的評論,Bernt。如果可能,用戶需要/需要查看缺少相應的logIn/LogOut存在的位置。例如,缺少匹配的LogOut的LogIn可能只是將其匹配LogOut設置爲NULL,並且我可以在rdlc中處理它。如果LogOut.Value = NULL,則在報告字段中顯示「Missing value」或類似內容。 – dlilleaa

回答

0

下面是一些基本代碼,可以處理您的示例數據,但可能需要進一步改進以解決您的業務規則。如果您可以根據這些規則提供符合您業務規則和預期結果的樣本數據,我可以重新修改代碼以使用它。

WITH Ranked AS (
--Ranking the rows to clean-up the data. 
SELECT TransactionDate, 
     [Type], 
     SalesDate, 
     --EmployeeGUID and DepartmentGUID should be added to the PARTITION BY section in a real scenario. For the sample data they are irrelevant. 
     Sequence = ROW_NUMBER() OVER(PARTITION BY SalesDate ORDER BY TransactionDate) 
FROM #EmployeeLogInOut 
), Clean AS (
--A more complex clean-up process can be in place here. Right now it just eliminates transactions where the type doesn't alternate from the previous one. 
SELECT TransactionDate, 
     [Type], 
     SalesDate 
FROM Ranked AS R 
WHERE NOT EXISTS (SELECT 1 FROM Ranked WHERE SalesDate = R.SalesDate AND Type = R.Type AND Sequence = R.Sequence - 1) 
--Previous CTEs can be bypassed and we can reference #EmployeeLogInOut instead of Clean, but we would get some "wrong" output for SalesDate 2011-09-06 
), LI AS (
SELECT SalesDate, 
     LogInTime = TransactionDate, 
     --EmployeeGUID and DepartmentGUID should be added to the PARTITION BY section in a real scenario. For the sample data they are irrelevant. 
     Sequence = ROW_NUMBER() OVER (PARTITION BY SalesDate ORDER BY TransactionDate) 
FROM Clean 
WHERE [Type] = 1 
), LO AS (
SELECT SalesDate, 
     LogOutTime = TransactionDate, 
     --EmployeeGUID and DepartmentGUID should be added to the PARTITION BY section in a real scenario. For the sample data they are irrelevant. 
     Sequence = ROW_NUMBER() OVER (PARTITION BY SalesDate ORDER BY TransactionDate) 
FROM Clean 
WHERE [Type] = 2 
) 
SELECT LI.SalesDate, 
    LI.LogInTime, 
    LO.LogOutTime, 
    WorkTime = DATEDIFF(MINUTE, LI.LoginTime, LO.LogoutTime) 
FROM LI 
    LEFT JOIN LO ON LO.SalesDate = LI.SalesDate 
     AND LI.Sequence = LO.Sequence; 

這將產生以下結果:

SalesDate LogInTime LogOutTime WorkTime 
2011-09-05 00:00:00.000 2011-09-05 16:59:39.000 2011-09-05 21:57:22.000 298 
2011-09-06 00:00:00.000 2011-09-06 16:59:37.000 2011-09-06 17:35:41.430 36 
2011-09-06 00:00:00.000 2011-09-06 17:37:41.000 2011-09-07 00:45:32.000 428 
2011-09-08 00:00:00.000 2011-09-08 17:12:19.000 2011-09-08 20:58:17.000 226 
2011-09-20 00:00:00.000 2011-09-20 20:09:10.000 2011-09-21 06:59:00.000 650 
2011-09-21 00:00:00.000 2011-09-21 17:06:49.000 2011-09-21 22:05:29.000 299 
2011-09-21 00:00:00.000 2011-09-21 22:06:55.000 2011-09-21 22:09:04.000 3