Добрый вечер, пытаюсь написать отчёт с помощью СКД по двум РС в один попадает время начала работы в другой время окончание работы в отчёт нужно вывести дни отработанные по работнику и часы. Часы соответственно сложить в итого. Как это можно сделать через набор данных - объект или набор данных объединение?
---
встречался с такой задачей))
помимо подсчета часов на работе, еще подсвечивал проблемных сотрудников, по которым нужно было самому редактировать записи в регистре, чтобы корректно выводился отчете, + разобратся почему сотрудник выходя или входя через проходную не захотел воспользоваться пропуском
проблемные сотрудники:
- у которых смена больше 10 часов (были случаи, когда разница одного входа и выхода > 10 часов)
- двойной вход
- двойной выход

```1c
    ВЫБРАТЬ
    Период,
    Сотрудник,
    ИСТИНА КАК ВходВыход
    ПОМЕСТИТЬ ТаблицаДанных
    ИЗ
    РегистрСведений.Входы

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ
    Выход.Период,
    Выход.Сотрудник,
    ЛОЖЬ
    ИЗ
    РегистрСведений.Выход КАК Выход
    //контроль правильно введенных данных... сотрудник будет отображаться как проблемный
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Входы КАК Входы
    ПО Выход.Период = Входы.Период
    И Выход.Сотрудник = Входы.Сотрудник
    ГДЕ
    Входы.Сотрудник ЕСТЬ NULL
    ;

    ВЫБРАТЬ
    ТаблицаДанных.Сотрудник,
    ТаблицаДанных.ПериодНачала,
    ТаблицаДанныхНачала.ВходВыход КАК ВходВыходНачала,
    ТаблицаДанных.ПериодОкончания,
    ТаблицаДанныхОкончания.ВходВыход КАК ВходВыходОкончания,
    ТаблицаДанныхОкончания.ВходВыход ЕСТЬ NULL
    ИЛИ (ТаблицаДанныхНачала.ВходВыход = ТаблицаДанныхОкончания.ВходВыход)
    ИЛИ РАЗНОСТЬДАТ(ТаблицаДанных.ПериодНачала, ТаблицаДанных.ПериодОкончания, ЧАС) > 10 КАК Проблемный
    ИЗ
    (ВЫБРАТЬ
    ТаблицаДанных.Сотрудник,
    ТаблицаДанных.Период КАК ПериодНачала,
    МИНИМУМ(ТаблицаДанных1.Период) КАК ПериодОкончания
    ИЗ
    ТаблицаДанных
    ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанных КАК ТаблицаДанных1
    ПО ТаблицаДанных.Сотрудник = ТаблицаДанных1.Сотрудник
    И ТаблицаДанных.Период < ТаблицаДанных1.Период
    СГРУППИРОВАТЬ ПО
    ТаблицаДанных.Сотрудник,
    ТаблицаДанных.Период) КАК ТаблицаДанных
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаДанных КАК ТаблицаДанныхНачала
    ПО ТаблицаДанных.Сотрудник = ТаблицаДанныхНачала.Сотрудник
    И ТаблицаДанных.ПериодНачала= ТаблицаДанныхНачала.Период
    ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанных КАК ТаблицаДанныхОкончания
    ПО ТаблицаДанных.Сотрудник = ТаблицаДанныхОкончания.Сотрудник
    И ТаблицаДанных.ПериодОкончания= ТаблицаДанныхОкончания.Период
    ГДЕ
    ТаблицаДанныхОкончания.ВходВыход ЕСТЬ NULL
    ИЛИ (НЕ ТаблицаДанныхНачала.ВходВыход И ТаблицаДанныхОкончания.ВходВыход)
```

в итоге получаете таблицу с данными с которой потом высчитываете нужные данные

p.s. код писал с головы, так что нужно будет его немного допилить, но думаю что суть понятна ;))
---
вот посмотрите тестовый запрос, пример, с расчетом часом
по ближайшим отметкам Приход - Уход, все остальное считается ошибкой и не рассчитывается

```1c
    Выбрать ДатаВремя(2021,10,1,10,0,0) как Период, "Иванов" как Сотрудник, "Приход" как Тип Поместить Рег1
    объединить все Выбрать ДатаВремя(2021,10,1,18,0,0), "Иванов", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,10,0,0), "Иванов", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,12,0,0), "Иванов", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,1,11,0,0), "Петров", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,10,0,0), "Петров", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,12,0,0), "Петров", "Приход"
    ;
    Выбрать ДатаВремя(2021,10,1,19,0,0) как Период, "Иванов" как Сотрудник, "Уход" как Тип Поместить Рег2
    объединить все Выбрать ДатаВремя(2021,10,2,8,0,0), "Иванов", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,14,0,0), "Иванов", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,19,0,0), "Иванов", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,1,19,0,0), "Петров", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,11,0,0), "Петров", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,19,0,0), "Петров", "Уход"
    ;
    //собираем общую таблицу Приход - Уход
    Выбрать * поместить Пром1 из Рег1
    объединить все
    Выбрать * из Рег2
    ;
    //сортируем и нумеруем
    Выбрать первые 1000 АВТОНОМЕРЗАПИСИ() как Номер,* Поместить Пром2 из Пром1
    упорядочить по
    Сотрудник,
    Период
    ;

    Выбрать
    Таб1.Сотрудник,
    Таб1.Период как Приход,
    Таб2.Период как Уход,
    РАЗНОСТЬДАТ(Таб1.Период, ЕстьNull(Таб2.Период,Таб1.Период), Час) как Часы
    из
    Пром2 Таб1
    левое соединение Пром2 Таб2
    по Таб1.Сотрудник = Таб2.Сотрудник
    и Таб1.Номер = Таб2.Номер - 1
    и Таб1.Тип <> Таб2.Тип
    где
    Таб1.Тип = "Приход"
```
---
Количество отработанных часов считается по формуле Строка(СУММА(ЧАС(ВремяОкончанияРаботы)) - СУММА(ЧАС(ВремяНачалаРаботы))) формула помещается в СКД во вкладке ресурсы, в поле по которому нужно вывести итог, в поле выражение.
---
для построения не хватает описания ограничений
1.есть ли ночные смены, это когда рабочий день начинается вечером и заканчивается в следующем дне?
2.в течении дня может ли рабочий период разбиваться на несколько частей? т.е. несколько приходов и уходов
3. если в течении дня нет одной из отметок, начала или окончания, то что брать за умолчание? стандарт с 10:00 до 19:00 ?
4. что там еще?
---
1.есть ли ночные смены, это когда рабочий день начинается вечером и заканчивается в следующем дне? Да есть. Начал допусти 19:00 а закончил 00:50

2.в течении дня может ли рабочий период разбиваться на несколько частей? т.е. несколько приходов и уходов. Это всё регулируется первой и второй сменой при отборе она учитывается

3. если в течении дня нет одной из отметок, начала или окончания, то что брать за умолчание? стандарт с 10:00 до 19:00 ? Нет и нет значит не работал в это день и в отчёт не попадает

4. что там еще? Да вроде всё.
---
(3)Разобрался, несколько упростил задачу свёл всё в один РС может подскажете как можно средствами СКД посчитать количество отработанных часов?
---
Количество отработанных часов считается по формуле Строка(СУММА(ЧАС(ВремяОкончанияРаботы)) - СУММА(ЧАС(ВремяНачалаРаботы))) формула помещается в СКД во вкладке ресурсы, в поле по которому нужно вывести итог, в поле выражение.
---
встречался с такой задачей))
помимо подсчета часов на работе, еще подсвечивал проблемных сотрудников, по которым нужно было самому редактировать записи в регистре, чтобы корректно выводился отчете, + разобратся почему сотрудник выходя или входя через проходную не захотел воспользоваться пропуском
проблемные сотрудники:
- у которых смена больше 10 часов (были случаи, когда разница одного входа и выхода > 10 часов)
- двойной вход
- двойной выход

```1c
    ВЫБРАТЬ
    Период,
    Сотрудник,
    ИСТИНА КАК ВходВыход
    ПОМЕСТИТЬ ТаблицаДанных
    ИЗ
    РегистрСведений.Входы

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ
    Выход.Период,
    Выход.Сотрудник,
    ЛОЖЬ
    ИЗ
    РегистрСведений.Выход КАК Выход
    //контроль правильно введенных данных... сотрудник будет отображаться как проблемный
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Входы КАК Входы
    ПО Выход.Период = Входы.Период
    И Выход.Сотрудник = Входы.Сотрудник
    ГДЕ
    Входы.Сотрудник ЕСТЬ NULL
    ;

    ВЫБРАТЬ
    ТаблицаДанных.Сотрудник,
    ТаблицаДанных.ПериодНачала,
    ТаблицаДанныхНачала.ВходВыход КАК ВходВыходНачала,
    ТаблицаДанных.ПериодОкончания,
    ТаблицаДанныхОкончания.ВходВыход КАК ВходВыходОкончания,
    ТаблицаДанныхОкончания.ВходВыход ЕСТЬ NULL
    ИЛИ (ТаблицаДанныхНачала.ВходВыход = ТаблицаДанныхОкончания.ВходВыход)
    ИЛИ РАЗНОСТЬДАТ(ТаблицаДанных.ПериодНачала, ТаблицаДанных.ПериодОкончания, ЧАС) > 10 КАК Проблемный
    ИЗ
    (ВЫБРАТЬ
    ТаблицаДанных.Сотрудник,
    ТаблицаДанных.Период КАК ПериодНачала,
    МИНИМУМ(ТаблицаДанных1.Период) КАК ПериодОкончания
    ИЗ
    ТаблицаДанных
    ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанных КАК ТаблицаДанных1
    ПО ТаблицаДанных.Сотрудник = ТаблицаДанных1.Сотрудник
    И ТаблицаДанных.Период < ТаблицаДанных1.Период
    СГРУППИРОВАТЬ ПО
    ТаблицаДанных.Сотрудник,
    ТаблицаДанных.Период) КАК ТаблицаДанных
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаДанных КАК ТаблицаДанныхНачала
    ПО ТаблицаДанных.Сотрудник = ТаблицаДанныхНачала.Сотрудник
    И ТаблицаДанных.ПериодНачала= ТаблицаДанныхНачала.Период
    ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанных КАК ТаблицаДанныхОкончания
    ПО ТаблицаДанных.Сотрудник = ТаблицаДанныхОкончания.Сотрудник
    И ТаблицаДанных.ПериодОкончания= ТаблицаДанныхОкончания.Период
    ГДЕ
    ТаблицаДанныхОкончания.ВходВыход ЕСТЬ NULL
    ИЛИ (НЕ ТаблицаДанныхНачала.ВходВыход И ТаблицаДанныхОкончания.ВходВыход)
```

в итоге получаете таблицу с данными с которой потом высчитываете нужные данные

p.s. код писал с головы, так что нужно будет его немного допилить, но думаю что суть понятна ;))
---
вот посмотрите тестовый запрос, пример, с расчетом часом
по ближайшим отметкам Приход - Уход, все остальное считается ошибкой и не рассчитывается

```1c
    Выбрать ДатаВремя(2021,10,1,10,0,0) как Период, "Иванов" как Сотрудник, "Приход" как Тип Поместить Рег1
    объединить все Выбрать ДатаВремя(2021,10,1,18,0,0), "Иванов", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,10,0,0), "Иванов", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,12,0,0), "Иванов", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,1,11,0,0), "Петров", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,10,0,0), "Петров", "Приход"
    объединить все Выбрать ДатаВремя(2021,10,2,12,0,0), "Петров", "Приход"
    ;
    Выбрать ДатаВремя(2021,10,1,19,0,0) как Период, "Иванов" как Сотрудник, "Уход" как Тип Поместить Рег2
    объединить все Выбрать ДатаВремя(2021,10,2,8,0,0), "Иванов", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,14,0,0), "Иванов", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,19,0,0), "Иванов", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,1,19,0,0), "Петров", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,11,0,0), "Петров", "Уход"
    объединить все Выбрать ДатаВремя(2021,10,2,19,0,0), "Петров", "Уход"
    ;
    //собираем общую таблицу Приход - Уход
    Выбрать * поместить Пром1 из Рег1
    объединить все
    Выбрать * из Рег2
    ;
    //сортируем и нумеруем
    Выбрать первые 1000 АВТОНОМЕРЗАПИСИ() как Номер,* Поместить Пром2 из Пром1
    упорядочить по
    Сотрудник,
    Период
    ;

    Выбрать
    Таб1.Сотрудник,
    Таб1.Период как Приход,
    Таб2.Период как Уход,
    РАЗНОСТЬДАТ(Таб1.Период, ЕстьNull(Таб2.Период,Таб1.Период), Час) как Часы
    из
    Пром2 Таб1
    левое соединение Пром2 Таб2
    по Таб1.Сотрудник = Таб2.Сотрудник
    и Таб1.Номер = Таб2.Номер - 1
    и Таб1.Тип <> Таб2.Тип
    где
    Таб1.Тип = "Приход"
```