AdamPL napisał(a)
Daj kod.
OK kod wygląda mniej więcej tak:
Na początku procedura FillRCP, której zadaniem jest włożyć rekordy do tabeli RCP.
Pola w tabeli RCP: (ID; employeeID; startDate; firstIn; lastOut; workTime; late; overtime; earlyIn; earlyOut; matchedShift)
I teraz tak, startDate to data rozpoczęcia pracy. firstIn, lastOut - wiadomo. Dodatkowo lastOut może być dzień później niż firstIn ;>
workTime - efektywny czas pracy, czyli nie lastOut - firstIn, ale wyklucza wszystkie wyjścia niesłużbowe pracownika w dniu. MatchedShift - ID dopasowanej zmiany, jeśli pracownik ma mieć automatycznie dopasowaną zmianę do swojego wejścia.
Wiemy już, co ma zawierać tabela RCP, a teraz jej wypełnianie. Procedura FillRCP:
ALTER PROCEDURE [dbo].[FillRcp]
@startDate datetime = null,
@stopDate datetime = null,
@employeeID bigint = null
AS
BEGIN
SET NOCOUNT ON
TRUNCATE TABLE RCP
DECLARE @firstIn DATETIME
DECLARE @lastOut DATETIME
DECLARE @late int --spóźnienie
DECLARE @overtime int --nadgodziny
DECLARE @workTime int --czas pracy
DECLARE @endWorkDate datetime
DECLARE @matchedShift bigint
DECLARE @earlyIn datetime --wcześniejsze wejście
DECLARE @earlyOut datetime --wcześniejsze wyjście
DECLARE @eid bigint
DECLARE @date datetime
-- ten select jest taki, a nie inny(distinct) ze względu na optymalizację
DECLARE ev CURSOR FOR
select a.employeeID, a.date
from
(
select employeeID, [dbo].get_date(date) as date
FROM [dbo].V_Events
where (@employeeID is null or @employeeID = employeeID) AND
(@startDate is null or @startDate<=[dbo].get_date(date)) AND
(@stopDate is null or @stopDate>=[dbo].get_date(date))
) as a
group by a.employeeID, a.date
order by a.employeeID, a.date
--powyższy select pobiera mi IDPracownika i daty jego odbić
OPEN ev
FETCH NEXT FROM ev INTO @eid, @date
WHILE @@FETCH_STATUS = 0
begin
if @eid is null
begin
FETCH NEXT FROM ev INTO @eid, @date
continue
end
SET @firstIn = null
SET @endWorkDate = null
SET @lastOut = null
SET @late = null
SET @overtime = null
SET @earlyIn = null
SET @earlyOut = null
--teraz wywołuję kilka swoich funkcji
--pobieram wejście
SET @firstIn = [dbo].getFirstIn(@eid, @date)
--pobieram datę końca pracy
SET @EndWorkDate = [dbo].getEndDate(@eid, @date)
--pobieram wyjście
SET @lastOut = [dbo].GetLastOut(@eid, @EndWorkDate)
--liczę spóźnienie itp
execute CalculateLateOver @eid, @firstIn, @lastOut, @late output, @overtime output, @matchedShift output
--jeśli spóźnienie <0 to jest to wcześniejsze wejście
if @late<0
begin
SET @earlyIn = [dbo].secToTime(abs(@late))
SET @late = 0
end
if @overtime<0
begin
SET @earlyOut = [dbo].secToTime(abs(@overtime))
SET @overtime = 0
end
--liczę czas pracy
execute CalculateWorkTime @eid, @firstIn, @lastOut, @workTime output
--robię insert
INSERT INTO rcp(employeeID, startDate, firstIn, lastOut, workTime,
late, overtime, earlyIn, earlyOut, matchedShift)
VALUES (@eid, @date, @firstIn, @lastOut, [dbo].secToTime(@workTime),
[dbo].secToTime(@late), [dbo].secToTime(@overtime),
@earlyIn, @earlyOut, @matchedShift)
FETCH NEXT FROM ev INTO @eid, @date
end
CLOSE ev
DEALLOCATE ev
END
Generalnie ta procedura wg planu zajmuje 30%. Nie znam się za bardzo na czytaniu planów, ale podejrzewam, że te 30% to czas funkcji i procedur wywoływanych przez tą :)
Kursor mam też w procedurze CalculateWorkTime. Pobieram w niej wszystkie odbicia dla danego pracownika pomiędzy firstIn i lastOut w danym dniu pracy. Następnie sprawdzam, czy odbicie jest wejściem, wyjściem, czy wyjściem służbowym. A konkretnie, czy wliczać je do czasu pracy, czy nie. No i później sumuję.