Выбор времени смены на основе первого входа в систему и последнего выхода из системы - PullRequest
0 голосов
/ 09 мая 2020

У меня есть 3 базы данных, которые включают одну и ту же таблицу «acc_monitor_log», такую ​​как идентификатор сотрудника в качестве PIN-кода и время входа, например, вход и выход, пример acc_monitor_log:

    time    pin state
2020-05-05 08:14:47.000 240 0
2020-05-05 15:32:21.000 240 1
2020-05-06 08:04:32.000 240 0
2020-05-06 08:04:37.000 240 0
2020-05-06 09:39:16.000 240 1
2020-05-06 10:04:17.000 240 0
2020-05-06 15:28:54.000 240 1

где PIN-код - это код сотрудника и состояние 0 - время входа, а 1 - выход

и мы работаем в 3 смены, смена 1 «8 часов» с 8 утра до 4 вечера и смена 2 «8 часов» с 16 до 23 часов. и сдвинуть 3 «9 часов» с 23:00 до 8:00

То, что я пробовал:

    declare 
@tbl table(pin nvarchar(50),_shift nvarchar(20),_in datetime,_out datetime)
declare 
@tblfinal table(serial int,pin nvarchar(50),_shift nvarchar(20),dd int,mm int,_in datetime,_out datetime)
declare 
@shift1start time = '06:30:00',
@shift1end time ='20:30:00',
@shift2start time ='13:00:00',
@shift2end time = '09:30:00',
@startdate date = '2020-04-25',
@enddate date = '2020-04-25'  

while @startdate != '2020-05-08'
begin

begin
with cte_ as (
SELECT  abc.pin , 
(SELECT min(time)
FROM [TUBE1].[dbo].[acc_monitor_log] 
where convert(date,time) between @startdate and @enddate and state =0 and pin=abc.pin)_in,
(SELECT max(time) FROM [TUBE1].[dbo].[acc_monitor_log]
where convert(date,time) between @startdate and @enddate
and state = 1 and pin=abc.pin)_out
FROM [TUBE1].[dbo].[acc_monitor_log] abc
where convert(date,time) between @startdate and @enddate
group by pin)
,

cte_2 as (
SELECT abc.pin ,
--min(time) _in,
(SELECT min(time)
FROM [TUBE2].[dbo].[acc_monitor_log] 
where convert(date,time) between @startdate and @enddate
and state =1
and pin=abc.pin)_in,
(SELECT max(time)
FROM [TUBE2].[dbo].[acc_monitor_log]
where convert(date,time) between @startdate and @enddate
and state = 0
and pin=abc.pin)_out
FROM [TUBE2].[dbo].[acc_monitor_log] abc
where convert(date,time) between @startdate and @enddate
group by pin),

--order by pin asc

cte_3 as (
SELECT abc.pin ,
--min(time) _in,
(SELECT min(time)
FROM [TUBE3].[dbo].[acc_monitor_log] 
where convert(date,time) between @startdate and @enddate
and state =0
and pin=abc.pin)_in,
--max(time) _out
(SELECT max(time)
FROM [TUBE3].[dbo].[acc_monitor_log]
where convert(date,time) between @startdate and @enddate
and state = 1
and pin=abc.pin)_out
FROM [TUBE3].[dbo].[acc_monitor_log] abc
where convert(date,time) between @startdate and @enddate
--and min(time) having state=0
--and pin=10
group by pin)

--order by pin asc
insert into @tbl 

select cte_.pin,
case 
when convert(time,cte_._in) between @shift1start and @shift1end 
and  convert(time,cte_._out) between @shift1start and @shift1end then '1'
when convert(time,cte_._in) between @shift2start and @shift2end 
and  convert(time,cte_._out) between @shift2start and @shift2end then '2'
else 'unkown'

end as _sift,
cte_._in,cte_._out 
from cte_

union

select cte_2.pin,
case
when convert(time,cte_2._in) between @shift1start and @shift1end 
and  convert(time,cte_2._out) between @shift1start and @shift1end then '1'
when convert(time,cte_2._in) between @shift2start and @shift2end 
and  convert(time,cte_2._out) between @shift2start and @shift2end then '2'
else 'unkown'
end as _sift,
cte_2._in,cte_2._out 
from cte_2

union

select cte_3.pin,
case 
when convert(time,cte_3._in) between @shift1start and @shift1end 
and convert(time,cte_3._out) between @shift1start and @shift1end then '1'
when convert(time,cte_3._in) between @shift2start and @shift2end 
and  convert(time,cte_3._out) between @shift2start and @shift2end then '2'
else 'unkown'
end as _sift,
cte_3._in,cte_3._out 
from cte_3
order by pin

end 
set @startdate = dateadd(day,1,@startdate)
set @enddate = dateadd(day,1,@enddate)
end

declare @pinn int = 0
while @pinn <=600
begin
insert into @tblfinal
select row_number() over (partition by dd,mm order by dd,mm)as serial,* from 
(select pin,_shift,datepart(day,_in) dd,datepart(MONTH,_in) mm,_in,_out from @tbl )a
where pin = @pinn

set @pinn = @pinn+1
end


select pin,_shift,min(_in) _in_,max(_out) _out_ from
(
select RIGHT('0000'+ISNULL(pin,''),4) as pin,_shift,_in,convert(date,_in)datein,_out ,convert(date,_out) dateout
from @tblfinal 
where serial = 1

)aa
where (datein = dateout or dateout = dateadd(day,1,datein) or datein is null or dateout is null)
group by pin,_shift,case when datein is not null then datein else dateout end
order by pin

, но я получил результат с множеством значений NULL и не t получить правильное время

0006    1   2020-04-26 14:53:54.000 2020-04-26 08:08:03.000
0006    1   2020-05-03 14:52:24.000 2020-05-03 07:59:05.000
0006    unkown  2020-04-25 14:59:34.000 NULL
0006    unkown  NULL    2020-04-27 07:54:17.000
0006    unkown  2020-05-02 15:10:04.000 NULL
0006    unkown  2020-05-06 15:04:28.000 NULL

1 Ответ

0 голосов
/ 09 мая 2020

я нашел решение, но оно не выходит во второй день для смены 3 вот так

0006 05.06.2020 15: 04
0006 05.07.2020 08:05

этот пользователь приходит на работу в 15:04 и уходит с работы в 08:05, но в тот же день отображается нет

;WITH CTE AS(
        SELECT
            RIGHT('0000'+ISNULL(pin,''),4) as pin,
            AccessDate = CAST(time AS DATE),
            time = CAST(time AS TIME),
            state,
            In_RN = ROW_NUMBER() OVER(PARTITION BY pin, CAST(time AS DATE), state ORDER BY CAST(time AS TIME) ASC),
            Out_RN = ROW_NUMBER() OVER(PARTITION BY pin, CAST(time AS DATE), state ORDER BY CAST(time AS TIME) DESC)
        FROM [TUBE1].[dbo].[acc_monitor_log]
        --where pin = 418 
        where convert(date,time) between '2020-04-27' and '2020-05-09'
    )
    SELECT
        pin,
        [Date] = CONVERT(VARCHAR(10), AccessDate, 101),
        InTime= ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN state= '0' AND In_RN = 1 THEN time END)), 1, 5), ''),
        OutTime = ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN state= '1' AND OUT_RN = 1 THEN time END)), 1, 5), ''),
        Duration =  ISNULL(RIGHT('00' +             
                    CONVERT(VARCHAR(2), DATEDIFF(MINUTE, 
                        MAX(CASE WHEN state= '0' AND In_RN = 1 THEN time END), 
                        MAX(CASE WHEN state= '1' AND OUT_RN = 1 THEN time END)
                    )/60), 2) + ':' +
                    RIGHT('00' +CONVERT(VARCHAR(2), DATEDIFF(MINUTE, 
                        MAX(CASE WHEN state= '0' AND In_RN = 1 THEN time END), 
                        MAX(CASE WHEN state= '1' AND OUT_RN = 1 THEN time END)
                    )%60), 2)
                ,'')
    FROM CTE
    GROUP BY pin, AccessDate
    ORDER BY  pin
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...