powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Посчитать время присутствия по паре строк ВХОД и ВЫХОД
23 сообщений из 23, страница 1 из 1
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481169
sss71
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

Вот такой вопрос образовался:
Имеется таблица REG_EVENTS, в которой содержатся события входа и выхода.
Идентификатор человека, дата и время события и, последнее, тип события
IDENTIFIER, DATE_EV, TIME_EV, AREAS_ID
Первые три очевидны, последнее - если =1, то это выход, иначе вход.
Требуется найти продолжительность присутствия для каждого случая, т.е. выход минус вход.
В таблице идут строки последоватеьно: ВХОД-ВЫХОД-ВХОД-...
Единственное, на что меня хватило, вот такой селект:

select a.identifier, a.date_ev, min(time_ev), max(time_ev) from REG_EVENTS a group by a.IDENTIFIER, a.date_ev

т.е. игнорируем промежуточные входы-выходы и в пределах одного дня всё замечательно.
Но желательно и промежуточные посчитать, но самое главное, вход может быть сегодня, а выход завтра, и вот тут группировка по дате не прокатывает.
В фоксе подобное решается перебором строк, а вот как это сделать SQL-запросом, тут я не знаю.
Посоветуйте, в какую сторону копать?

С уважением, Сергей.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481202
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sss71, в сторону процедур, конечно же
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481204
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sss71DATE_EV, TIME_EV
Кто такое придумал? Почему не timestamp?
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481212
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sss71,

Я бы добавил поле "длительность" и вычислял его в триггере при заполнении поля "время выхода", а в запросах суммировал бы длительность. Правда, если есть варианты типа "зашел сегодня, а вышел через год" и посчитать надо только то, что сегодня, прямое суммирование не проканает. А еще бы учесть, что можно (ошибочно) зайти сегодня, а выйти послезавтра и тогда надо думать, как вычислить (и надо ли) завтра.

Это все я к тому, что маловато входных данных.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481219
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonline,

Тьфутыблин, показалось, что вход и выход содержатся в одной записи.

Но все равно, одним селектом такое разве что Таблоид сделает, если у него будет «час і натхнення»© (время и вдохновение). :)
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481223
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonlineНо все равно, одним селектом
Как он осилит, когда один зашел, а вышли - два? А десять? У нас на всех дверях и по одному пропуску может хоть цех выйти. И только на проходной стоит крутилка и только там каждый проходит отдельно.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481322
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И то, все эти крутилки имеют вероятность глюкнуть, сломаться. Надо сразу закладываться на то, что будут встречаться "рваные" данные. Если у вас нет круглосуточных фахт, я бы посоветовал при отсутствии факта ухода/прихода принудительно ставить время ухода/прихода полуночью (либо официальным временем окончания/начала рабочего дня). Ну и заодно добавить признак, что это время не соответствует реальности (для отчета о багах и в конфликтных ситуациях).
соответственно при такой логике одним запросом не обойтись. Ну а с ХП можно и перебор сделать
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481353
TurutaSergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wadmansss71DATE_EV, TIME_EV
Кто такое придумал? Почему не timestamp?

Согласен.
Из стартпоста не понятно какая СУБД,
но я начал бы с того, что объеденил два поля DATE_EV, TIME_EV в одно DATE_TIME_EV.

в итоге получаем следующее:
IDENTIFIER, DATE_TIME_EV, AREAS_ID
Не претендую на самый быстрый вариант. И одним select тут не обойтись.

если вложенные select в вашей СУБД прокатят, то ход мыслей следующий:

сканируем дважды таблицу для входов (A) и для выходов (B).

select A.IDENTIFIER, A.DATE_TIME_EV as TIME_A, B.DATE_TIME_EV as TIME_B

from
(select IDENTIFIER, DATE_TIME_EV where AREAS_ID != 1) A, -- входы
(select IDENTIFIER, DATE_TIME_EV where AREAS_ID = 1) B -- выходы
where (A.IDENTIFIER = B.IDENTIFIER)
and (B.DATE_TIME_EV > A.DATE_TIME_EV) -- в этом месте отбираем только те выходы, которые были после входа
group by A.IDENTIFIER
having (B.DATE_TIME_EV - A.DATE_TIME_EV) = MIN (B.DATE_TIME_EV - A.DATE_TIME_EV) -- в этом месте отбираем те выходы, которые со входом имеют минимальную разницу во времени.

на движке не проверял. Может, рабочий запрос будет выглядеть немного по-другому. Но общая идея такова.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481420
TurutaSergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
так лучше будет:

select A.IDENTIFIER, A.DATE_TIME_EV as TIME_A,
MIN(B.DATE_TIME_EV) as TIME_B -- в этом месте отбираем те выходы, которые следуют сразу после входа.

from
(select IDENTIFIER, DATE_TIME_EV where AREAS_ID != 1) A, -- входы
(select IDENTIFIER, DATE_TIME_EV where AREAS_ID = 1) B -- выходы
where (A.IDENTIFIER = B.IDENTIFIER)
and (B.DATE_TIME_EV > A.DATE_TIME_EV) -- в этом месте отбираем только те выходы, которые были после входа
group by A.IDENTIFIER, A.DATE_TIME_EV

даже заработать сразу должен, после того как DATE_EV, TIME_EV будут объедены в одно поле DATE_TIME_EV.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481471
TurutaSergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Fr0sT-BrutalИ то, все эти крутилки имеют вероятность глюкнуть, сломаться. Надо сразу закладываться на то, что будут встречаться "рваные" данные. Если у вас нет круглосуточных фахт, я бы посоветовал при отсутствии факта ухода/прихода принудительно ставить время ухода/прихода полуночью (либо официальным временем окончания/начала рабочего дня). Ну и заодно добавить признак, что это время не соответствует реальности (для отчета о багах и в конфликтных ситуациях).
соответственно при такой логике одним запросом не обойтись. Ну а с ХП можно и перебор сделать

Предлагаю рассмотреть пример.

рабочий день с 9:00 до 18:00
перерыв с 13:00 до 14:00

1. Законопослушный вариант:
вход 8:55
выход 13:05
вход 13:55
выход 18:05

Итог: первый вх-вых (4:10) + второй вх-вых (4:10) = 8:20 время в офисе

2. Вариант, в котором сотрудник "забыл" отметить выход на перерыв:
вход 8:55
выход: отсутствует
вход 13:55
выход 18:05

Итог: первый вх-вых (9:10) + второй вх-вых (4:10) = 13:20 (!) время в офисе при 8-ми часовом дне
поэтому, при отсутствующих данных два входа или два выхода подряд нужно принимать решение, что с этим делать.
возможно, ввести "презумпцию виновности": если входа подряд, то первый вход не учитывать. Учитывать только второй.

тогда у "забывчивых" сотрудников будет стимул не забывать отмечаться:
Итог для "забывчивых": первый вх-вых (0:00) + второй вх-вых (4:10) = 4:10 тогда это будет правильно.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481816
sss71
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Некоторое время интернет не работал, потому отвечу всем в одном письме:

1. База существует как есть и заполняется не мной. Никаких полей я туда добавлять не могу. Я лишь хочу получать выборки из неё, отличные от стандартного функционала.
2. Ходить всем по одному пропуску не дадут суровые дяди, варианты с двумя входами и одним выходом исходной программой предусмотрены и соответственно помечаются. Я не стал на них заострять внимание, т.к. сам отфильтрую без проблем. Варианты с отключением света и т.п. тоже имеются в виду. Они у меня тупо записаны на бумажку, и при анализе выборки учитывается, что такому-то числу верить нельзя.
3. Процедурами не владею, но
4. вот идея с двумя селектами из одной таблицы в качестве источников мне понравилась. Буду копать в эту сторону.


Спасибо всем ответившим!
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481826
sss71
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СУБД - Firbird SQL 2.5
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38481847
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sss71СУБД - Firbird SQL 2.5
Эх, а я только собрался посоветовать функцию LAG()...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482205
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sss71желательно и промежуточные посчитать, но самое главное, вход может быть сегодня, а выход завтра DDL:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
recreate table t(   dts timestamp primary key using index t_dts_idx,
                    evt smallint,
                    constraint valid_evt check( evt in(1,2) )
                );
commit;

delete from t;
commit;
-- согласующийся вход-выход, "дневная смена":
insert into t values('15.11.2013 09:00:29', 1);
insert into t values('15.11.2013 17:58:31',2);

-- еще один согласующийся вход-выход, "ночная смена":
insert into t values('16.11.2013 21:19:24', 1);
insert into t values('16.11.2013 06:03:21',2);

-- только входы (бардак на проходной-1):
insert into t values('17.11.2013 09:10:10', 1);
insert into t values('17.11.2013 14:02:32', 1);
insert into t values('18.11.2013 09:01:11', 1);

-- только выходы (бардак на проходной-2):
insert into t values('19.11.2013 13:00:22',2);
insert into t values('19.11.2013 17:57:29',2);
insert into t values('20.11.2013 13:01:27',2);
insert into t values('20.11.2013 18:01:19',2);

-- множество согласованных входов-выходов за 1 день:
insert into t values('21.11.2013 08:54:55', 1);
insert into t values('21.11.2013 11:23:22',2);
insert into t values('21.11.2013 12:01:44', 1);
insert into t values('21.11.2013 13:02:22',2);
insert into t values('21.11.2013 14:06:26', 1);
insert into t values('21.11.2013 18:00:25',2);

-- разница между входом и выходом свыше 1 календарного дня
-- (т.е. вход "позавчера", а выход - "сегодня"), считается ошибкой:
insert into t values('22.11.2013 09:07:17', 1);
insert into t values('24.11.2013 18:00:21',2);
commit;
Query: (не сгруппированный; null в графе `was_here` означает ошибку в этом дне)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
with
c as(
select dts tc,evt ec,(select first 1 cast(x.dts as char(25))||cast(x.evt as char(1)) tx from t x where x.dts>t.dts) tx
from t
)
,d as(
select tc,ec,cast(left(tx,25) as timestamp) tx,cast(right(tx,1) as smallint) ex
from c
)
select tc,tx,ec,ex,  iif(ec < ex and cast(tx as date)-cast(tc as date)<=1, datediff(minute from tc to tx), null) was_here
from d
where ec=1
order by tc;

Выборку с учетом пользователей сделаете сами.
ЗЫ. Через процедуру будет быстрее, т.к. таблица будет пройдена только один раз.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482228
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В трёшке с оконными ф-циями всё проще и короче:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with
d as(
    select  dts tc
            ,evt ec
            ,lead(dts)over(order by dts) tx
            ,lead(evt)over(order by dts) ex
    from t
)
select tc,tx,ec,ex,  iif(ec < ex and cast(tx as date)-cast(tc as date)<=1, datediff(minute from tc to tx), null) was_here
from d
where ec=1

Но для поиска следующей строки в порядке возрастания даты не задействован индекс t_dts_idx, как того хотелось бы. Поэтому что там будет на большом числе строк - еще вопрос.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482231
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonlinemiwaonline,
Но все равно, одним селектом такое разве что Таблоид сделает, если у него будет «час і натхнення»© (время и вдохновение). :)

wadmanmiwaonlineНо все равно, одним селектом
Как он осилит, когда один зашел, а вышли - два? А десять?

Таблоид Query: (не сгруппированный; null в графе `was_here` означает ошибку в этом дне)

Выборку с учетом пользователей сделаете сами.
ЗЫ. Через процедуру будет быстрее, т.к. таблица будет пройдена только один раз.

Я знал
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482239
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonlineЯ знал а что тут сложного ?.. %-)
Смотрим, "что там дальше записано было", и применяем простые проверки.
ТС, возможно, еще что-то там недоговорил про их труд и быт, но это уже пусть сам дорёшивает.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482291
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид
Код: plaintext
(select first 1 cast(x.dts as char(25))||cast(x.evt as char(1)) tx from t x where x.dts>t.dts)
ooops! order by забыл, сорри. Вот так надо:
Код: plaintext
1.
(select cast(x.dts as char(25))||cast(x.evt as char(1)) tx from t x where x.dts>t.dts  order by x.dts rows 1 )
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482335
Евгений Болтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sss71Здравствуйте!
Идентификатор человека, дата и время события и, последнее, тип события
IDENTIFIER, DATE_EV, TIME_EV, AREAS_ID
Первые три очевидны, последнее - если =1, то это выход, иначе вход.
С уважением, Сергей.

А если сервер или программа упадет как отследишь? Выход некуда/некому записать. Может лучше каждые х секунд еще и говорить работает.
1 - вошел
2 - работает т.к х секунд оповещают
3 - вышел
4 - аварийный выход (это состояние тоже отслеживается) к примеру у меня более 2 минут нет сообщений значит отвалился.

А дальше, тут варианты предлагали, зашел и не вышел до завтра. Это тоже решается. Есть функции видовые "Простаивает ОС".
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482357
Kotъ-Begemotъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я для себя этот вопрос решил, хранением в одной строке и времени входа и выхода. На "сессию" получается ID и с этим пишется время входа, и при выходе - выхода. А чтобы, при каком-то сбое время выхода не осталось незаполненным, оно каждые несколько минут (и сразу при входе) заполняется текущим TIMESTAMP и признаком "автоматической" записи. А когда реально юзер выходит, ставится время выхода, и снимается флаг "автозаписи".
Зато считается всё потом элементарным запросом.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482369
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидВ трёшке с оконными ф-циями всё проще и короче:<...>
Но для поиска следующей строки в порядке возрастания даты не задействован индекс t_dts_idx, как того хотелось бы. Поэтому что там будет на большом числе строк - еще вопрос .Уже нет вопроса.
По кр мере, для таблицы с 15 лямами строк, в которую добавлялись случайные int-числа:
sample
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SQL> select count(*) from t;

             15813251

SQL> select * from t rows 10;

      384138
      633262
      582286
      263649
      282770
      188050
      623496
      499282
       19429
      134205
- оконная функция lead()over(order by x) явно рулит по сравнению со скалярным подзапросом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
SQL> set stat on;
SQL> set explain on;
SQL> select count(*) from (select tc.x,(select first 1 x from t tx where tx.x>tc.x order by tx.x) tx from t tc);

Select Expression
    -> Singularity Check
        -> First N Records
            -> Filter
                -> Table "TX" Access By ID
                    -> Index "T_X" Scan
Select Expression
    -> Aggregate
        -> Union
            -> Table "TC" Full Scan

             15813251

Current memory = 2450745104
Delta memory = 544752
Max memory = 2450796560
Elapsed time= 562.68 sec
Cpu = 0.05 sec
Buffers = 524288
Reads = 215467
Writes = 0
Fetches = 924779969

SQL> select count(*) from (select tc.x,lead(x)over(order by x) tx from t tc);

Select Expression
    -> Aggregate
        -> Window
            -> Record Buffer
                -> Table "TC" Full Scan

             15813251

Current memory = 2450734048
Delta memory = -11056
Max memory = 2536880256
Elapsed time= 122.29 sec
Cpu = 0.00 sec
Buffers = 524288
Reads = 0
Writes = 0
Fetches = 32017389
SQL> set explain off;
SQL> set stat off;
(проверял на SS, но в другом окне идёт еще один тест; впрочем, вряд ли и на "чистом" окружении будет по-другому).
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482377
TurutaSergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kotъ-BegemotъЯ для себя этот вопрос решил, хранением в одной строке и времени входа и выхода. На "сессию" получается ID и с этим пишется время входа, и при выходе - выхода. А чтобы, при каком-то сбое время выхода не осталось незаполненным, оно каждые несколько минут (и сразу при входе) заполняется текущим TIMESTAMP и признаком "автоматической" записи. А когда реально юзер выходит, ставится время выхода, и снимается флаг "автозаписи".
Зато считается всё потом элементарным запросом.

Мне нравится! Неплохой выход из ситуации. Дешиво и сердито.
А разгильдяйство человеческого фактора можно потом логикой победить.
...
Рейтинг: 0 / 0
Посчитать время присутствия по паре строк ВХОД и ВЫХОД
    #38482816
sss71
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Насчет входа и выхода в одной строке - не потянет. Если даже не считать того, что система уже построена и написана, то вход может быть в одно место, а выход из другого, или вход во внешние ворота, потом вход во внутренние. Тот самый признак areas_id = 1 на самом деле означает 1 - внешняя территория, а внутренних может быть много. Поэтому 1 - выход, а <>1 - вход, неважно куда.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Посчитать время присутствия по паре строк ВХОД и ВЫХОД
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]