Cześć, napisałem funkcję, ale podejrzewam, że można ją napisać lepiej.
Jest to zwykła funkcja skalarna, ma zadanie dopasować zmianę do pracownika.
Tzn.
Jest sobie pracownik. On o którejś godzinie rozpoczął pracę(wcale nie musiał zakończyć).
I jest tabela ze zmianami. Zmiana może się rozpocząć np. od godziny 08:00 do godziny 08:05 i zakończyć np. od godziny 16:00 do 16:05.
Mam nadzieję, że wszystko zrozumiałe póki co. No i teraz chodzi o to, żeby dopasować zmianę pracownikowi.
W tym momencie robię to tak, że:
Najpierw sprawdzam idealny przypadek, czyli taki, że pracownik wszedł i wyszedł idealnie w godzinach zmiany. Czyli wg powyższego przykładu wszedł powiedzmy o 08:01, a wyszedł o 16:00.
Jeśli jednak nie dopasowano żadnej zmiany, kolejnym krokiem jest próba dopasowania na podstawie samej godziny wejścia(co też nie jest do końca dobre).
Czyli biorę sobie dwie zmiany. 1. Pracownik wszedł przed rozpoczęciem zmiany, 2. pracownik wszedł po rozpoczęciu zmiany. Następnie mniejsza różnica(między wejściem pracownika i rozpoczęciem zmiany) oznacza, że to właśnie ta zmiana ma być dopasowana.
Ja w mojej funkcji mam:
1 zwykły SELECT
2 zagnieżdżone SELECTY w kolejnym SELECTcie.
Wygląda ona mniej więcej tak:
(mniej więcej, bo pomijam kilka nieistotnych dla zagadnienia warunków)
ALTER FUNCTION [dbo].[MatchShift]
(
@employeeID bigint, -- id pracownika
@firstIn DATETIME, -- pierwsze wejście pracownika
@lastOut DATETIME = null -- ostatnie wyjście pracownika
)
RETURNS bigint
AS
BEGIN
if @firstIn is null return null
DECLARE @result BIGINT
DECLARE @id BIGINT --pomocnicza
SET @firstIn = [dbo].get_time(@firstIn) -- pozbywam się części daty, zostaje sama godzina
-- najpierw zakładam najlepszy przypadek
if @lastOut is not null
BEGIN
SET @lastOut = [dbo].get_time(@lastOut) -- pozbywam się części daty, zostaje sama godzina
SELECT @result = ID
FROM [dbo].shifts
WHERE [dbo].get_time(beginFrom)>=@firstIn
AND [dbo].get_time(beginTo)<=@firstIn
AND [dbo].get_time(endFrom)>=@lastOut
AND [dbo].get_time(endTo)<=@lastOut
END
-- jeśli result jest nullem, znaczy, że koleś nie wpasował się idealnie
IF @result is null
begin
-- dopasowuję zmianę wg wejścia
SELECT top 1 @result = res.ID
FROM
(
SELECT top 1 ID, abs(datediff(second, [dbo].get_time(beginFrom), @firstIn)) as diff
FROM [dbo].shifts
WHERE [dbo].get_time(beginFrom)>=@firstIn
UNION ALL
SELECT top 1 ID, abs(datediff(second, [dbo].get_time(beginFrom), @firstIn)) as diff
FROM [dbo].shifts
WHERE [dbo].get_time(beginFrom)<=@firstIn
) as res
ORDER by res.diff asc
end
RETURN @result
END
No, to jakby ktoś miał jakiś pomysł na optymalizację tego(czy w ogóle sie da) i ewentualnie uwzględnienie też godziny wyjścia, to byłoby zajebiście.