В помощь кадровику. Отчет по состояниям (отклонениям) сотрудников за период.


     Моя переработанная статья будет полезна и работникам кадровых служб и разработчикам кадровых отчетов. Вся информация для пользователей размещена в самом начале статьи, ниже идет техническое описание сбора данных для отчета.
     К статье прикреплен  отчет на основе СКД, который позволяет в детальной и настраиваемой форме выводить информацию о состояниях сотрудников за выбранный период. Данные собираются исключительно с кадровых регистров. Через механизм характеристик реализована поддержка использования категорий и свойств объектов.

В описании для разработчиков я расскажу об основных принципах создания отчета по состояниям (отклонениям) сотрудников организаций  за выбранный период. Данные будем брать из регистров сведений «СостояниеРаботниковОрганизаций» и «РаботникиОрганизаций». В файлах выложен полностью работоспособный отчет по статье, который можно быстро адаптировать под Ваши учетные задачи.
(тестировалась в ЗУП 2.5.37.1, 2.5.54.1 / 8.2.14.533, 8.2.15.310)

 Отзывы и успешные внедрения

1) Резензия Ирины Кондратенко, руководитель HR-практикой, БИТ. (  http://www.1cbit.ru/events_detail.php?ID=130306&ref=46  ) 

Отчет актуальный, хорошая методологическая проработка. Вызывает уважение профессиональный (системный) подход автора к решению задачи - учтены не только нюансы кадрового учета сотрудников, но и вопросы производительности.
Можем рекомендовать нашим клиентам для использования.

2) Отчет внедрен в некоторых ДЗО ОАО РЖД.

3) Читай комментарии к отчету.

 

Описание для пользователей

Работая с кадровыми и расчетными службами в крупнейшем холдинге РФ, неизбежно сталкиваешься с проблемой сверки и сопоставления кадровых и расчетных данных.  В том случае, если учет невыходов оформляется кадровиками путем ввода документов-отклонений, а на основании этих документов вводятся расчетные документы, то возникновение ошибок в оформлении кадровых документов или их несвоевременная регистрация, может вести к неверному начислению зарплаты и как следствие некорректному расчету налогов. Следует принимать во внимание, что расчетчики оперируют понятием «вид расчета», в то время как кадровики – «состояние сотрудника». В этой связи обеспечение надежной связи между «состояниями сотрудников» и «видами расчетов», возможность ее проанализировать и, в случае необходимости, корректировать - краеугольная задача.

Данный отчет позволяет в детальной и настраиваемой форме выводить информацию о состояниях сотрудников за выбранный период. Данные собираются исключительно с кадровых регистров. С помощью этого отчета можно:

1)      Контролировать ввод документов отклонений и кадровых приказов на прием и увольнение

2)      Сверять кадровые состояния сотрудников с данными из отчета «Форма Т13 (табель)»

3)      Сверять кадровые состояния сотрудников с ведомостью начислений и сводом

4)      Компоновать в различных разрезах (хоть по гороскопу) данные по состояниям сотрудников.

 

Вы можете прямо сейчас скачать  отчет с этого сайта и начать им пользоваться! 

Если у Вас возникли какие-то сложности или есть вопросы и пожелания  - пишите на электронную почту: PanteleevI@Inbox.ru 

Буду признателен за поставленный "плюс" с вашей стороны, т.к. никакой другой заинтересованности у меня нет, а время потраченно было.

 

Примеры настроек отчета:

 

Основная настройка "По состояниям" :

Настройка отчета  

 

Экзотическая настройка "Состояния по гороскопу"  

Настройка отчета  

 

Настройка отчета "Для сверки табелей"  

Настройка отчета  

 

 

Описание для разработчиков и внедренцев

Более полутора лет назад создал отчет по состояниям (отклонениям). Он создавался для кадровиков и должен был собирать данные исключительно из "кадровых" регистров, т.е. без учета фактически оплаченных периодов. Конечно, просматривал кто и что сделал по этой теме, но стоящих работ не нашел. Решил изобрести удобный велосипед и таки добился своего. Затем было внедрение и продолжительная работа с замечаниями и пожеланиями. Сейчас после протяженного тестирования мне не стыдно поделиться некоторыми соображениями по этой теме.

 

1. Структура регистров для получения данных

Для решения задачи нам потребуются обработки:  «Консоль отчетов» и «Консоль отчетов».

Основные данные для отчета будем собирать с регистров сведений: «СостояниеРаботниковОрганизаций» и «РаботникиОрганизаций».

 Рассмотрим структуру этих регистров:

Структура регистров

Оба регистра периодические с периодичностью в пределах дня, подчиненные регистратору.

Они имеют два измерения «Сотрудник» и «Организация» (другие измерения, начинающиеся со слова «удалить»,  уже не используются и представляют собой аппендикс из прошлого).

Важно отметить, что в типовой конфигурации ЗУП 2.5.37.1 в этих регистрах проиндексировано измерение «Организация» и ресурс «Обособленное подразделение»:

Свойство измерения Организация регистра

Для чего нужно использовать индексирование? В таблице реляционной БД данные хранятся обычно в том порядке, в каком их ввели в таблицу. Такой способ позволяет быстро вводить данные, новые записи просто добавляются в конец таблицы. Но вот если нужно что-то быстро найти, то такой способ хранения обеспечивает некоторые трудности в плане производительности. При индексировании таблицы по измерению «Организация» таблица дополнительно упорядочивается по этому полю и при поиске нужно просматривать меньший объем данных.

Если у вас достаточно большой объем данных (от несколько десятков кадровых движений в день и отклонений), то имеет смысл задуматься,  не проиндексировать ли в конфигураторе измерение «Сотрудник»?  Практически во всех типовых запросах с использованием регистров сведений «СостояниеРаботниковОрганизаций» и «РаботникиОрганизаций» связь с другими таблицами осуществляется через поля «Сотрудник», так же очень часто на него накладываются различные условия. Аналогично с полями «Период завершения» и «ПричинаИзмененияСостояния».

 Замечу, что чрезмерное необоснованное индексирование может значительно ухудшить скорость записи данных в БД.

Откроем консоль отчетов, создадим новый отчет, назовем его «Отчет по состояниям».  

Создание отчета в консоли

В конструкторе компоновке данных добавляем набор данных запрос.

 набор данных

Далее работаем в конструкторе.

 

2. Первый пакет:  РС_РаботникиОрганизаций

Для того, чтобы получить отчет по состояниям за период нам нужно сначала получить список всех штатных (в т.ч. и совместителей) сотрудников за период. Получим их из регистра сведений «РаботникиОрганизаций».

Нам нужно получить все записи регистра за период. Для этого объединим реальные записи за период с таблицей среза последних на дату начала периода.

Схема получения сотрудников за период

Текст запроса первого пакета:

ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
	СотрудникиЗаПериод.Сотрудник,
	СотрудникиЗаПериод.Регистратор,
	СотрудникиЗаПериод.Период КАК Период,
	СотрудникиЗаПериод.ЗанимаемыхСтавок,
	СотрудникиЗаПериод.ОбособленноеПодразделение,
	СотрудникиЗаПериод.ПодразделениеОрганизации,
	СотрудникиЗаПериод.Должность,
	СотрудникиЗаПериод.ГрафикРаботы,
	СотрудникиЗаПериод.ПричинаИзмененияСостояния
ПОМЕСТИТЬ РС_РаботникиОрганизаций
ИЗ
	(ВЫБРАТЬ
		РаботникиОрганизацийСрезПоследних.Сотрудник КАК Сотрудник,
		РаботникиОрганизацийСрезПоследних.Регистратор КАК Регистратор,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.Период
		КОНЕЦ КАК Период,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ЗанимаемыхСтавокЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.ЗанимаемыхСтавок
		КОНЕЦ КАК ЗанимаемыхСтавок,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ОбособленноеПодразделениеЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.ОбособленноеПодразделение
		КОНЕЦ КАК ОбособленноеПодразделение,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизации
		КОНЕЦ КАК ПодразделениеОрганизации,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ДолжностьЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.Должность
		КОНЕЦ КАК Должность,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ГрафикРаботыЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.ГрафикРаботы
		КОНЕЦ КАК ГрафикРаботы,
		ВЫБОР
			КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостоянияЗавершения
			ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния
		КОНЕЦ КАК ПричинаИзмененияСостояния
	ИЗ
		РегистрСведений.РаботникиОрганизаций.СрезПоследних(НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ), Организация = &ПарамОрганизация) КАК РаботникиОрганизацийСрезПоследних
	ГДЕ
		(НЕ ВЫБОР
					КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
							И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
						ТОГДА РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостоянияЗавершения
					ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния
				КОНЕЦ = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Увольнение))
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		РаботникиОрганизаций.Сотрудник,
		РаботникиОрганизаций.Регистратор,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ПериодЗавершения
			ИНАЧЕ РаботникиОрганизаций.Период
		КОНЕЦ,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ЗанимаемыхСтавокЗавершения
			ИНАЧЕ РаботникиОрганизаций.ЗанимаемыхСтавок
		КОНЕЦ,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ОбособленноеПодразделениеЗавершения
			ИНАЧЕ РаботникиОрганизаций.ОбособленноеПодразделение
		КОНЕЦ,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ПодразделениеОрганизацииЗавершения
			ИНАЧЕ РаботникиОрганизаций.ПодразделениеОрганизации
		КОНЕЦ,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ДолжностьЗавершения
			ИНАЧЕ РаботникиОрганизаций.Должность
		КОНЕЦ,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ГрафикРаботыЗавершения
			ИНАЧЕ РаботникиОрганизаций.ГрафикРаботы
		КОНЕЦ,
		ВЫБОР
			КОГДА РаботникиОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
					И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА РаботникиОрганизаций.ПричинаИзмененияСостоянияЗавершения
			ИНАЧЕ РаботникиОрганизаций.ПричинаИзмененияСостояния
		КОНЕЦ
	ИЗ
		РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
	ГДЕ
		РаботникиОрганизаций.Организация = &ПарамОрганизация
		И РаботникиОрганизаций.Период > НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
		И РаботникиОрганизаций.Период <= КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)) КАК СотрудникиЗаПериод

ИНДЕКСИРОВАТЬ ПО
	СотрудникиЗаПериод.Сотрудник,
	Период

Количество полей.

9полей:  Сотрудник, Регистратор, Период , Организация,  ЗанимаемыхСтавой, Обособленное Подразделение, ПодразделениеОрганизации, Должность, ГрафикРаботы,  ПричинаИзмененияСостояния.

 5 ссылочных, 2 примитивных.

Количество записей.

Строк при выводе результата в тестовой базе 1750 с отбором за 2011 год.

Таблица результирующих записей (не вся):

         

1

 Александр

01.01.2011

Перемещение

Отделение эксплуатации

 

2

 Анатолий

01.01.2011

Перемещение

Сектор дизайна

 

3

 Анатолий

11.10.2011

Увольнение

Сектор дизайна

 

4

 Альбина

01.01.2011

Перемещение

Сектор организационного обеспечения

 

5

 Жанна

01.01.2011

Перемещение

Сектор методического обеспечения

 

6

 Ксения

01.01.2011

Перемещение

Отдел комплексных систем

 

7

 Ксения

13.05.2011

Увольнение

Отдел комплексных систем

 

Мы добились своей цели: отобрали все записи регистра сведений за период. При этом не забыли последние записи с увольнениями.

 

3. Второй пакет:  ВТ_ТаблицаСотрудников

В предыдущем пакете мы получили все актуальные записи регистра сведений «РаботникиОрганизаций». Теперь выберем из них уникальных сотрудников.

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	РС_РаботникиОрганизаций.Сотрудник КАК Сотрудник
ПОМЕСТИТЬ ВТ_ТаблицаСотрудников
ИЗ
	РС_РаботникиОрганизаций КАК РС_РаботникиОрганизаций

СГРУППИРОВАТЬ ПО
	РС_РаботникиОрганизаций.Сотрудник

ИНДЕКСИРОВАТЬ ПО
	Сотрудник;

Количество полей.

1поле:  Сотрудник

 1 ссылочное.

Количество записей.

Строк при выводе результата в тестовой базе 1140 с отбором за 2011 год.

 

4. Третий пакет: РС_СостоянияСотрудников

Получим все записи регистра сведений «СостояниеРаботниковОрганизаций» за 2011 год.

 Для этого объединим реальные записи за период с таблицей среза последних на дату начала периода.

 Схема получения записей из РС Состояния сотрудников организаций

Таблица записей регистра (с отбором по сотруднику за 2010 год):

           

1

 Александр Анатольевич

11.11.2009

В командировке

14.11.2009

Работает

 

2

 Александр Анатольевич

22.03.2010

В ежегодном отпуске

27.03.2010

Работает

 

3

 Александр Анатольевич

05.04.2010

В командировке

08.04.2010

Работает

 

4

 Александр Анатольевич

04.05.2010

В ежегодном отпуске

08.05.2010

Работает

 

5

 Александр Анатольевич

25.05.2010

В командировке

28.05.2010

Работает

 

6

 Александр Анатольевич

05.07.2010

В ежегодном отпуске

11.07.2010

Работает

 

7

 Александр Анатольевич

11.07.2010

В ежегодном отпуске

17.07.2010

Работает

 

8

 Александр Анатольевич

10.08.2010

В командировке

14.08.2010

Работает

 

9

 Александр Анатольевич

03.10.2010

В командировке

07.10.2010

Работает

 

10

 Александр Анатольевич

25.10.2010

В ежегодном отпуске

30.10.2010

Работает

 

11

 Александр Анатольевич

01.12.2010

В командировке

03.02.2011

Работает

 
               

В приведенном примере набора записей для нас прежде всего будут интересны первая и последняя строки. Поскольку мы формируем отчет с 01.01.2010, то первую строку нужно преобразовать так, чтобы «период завершения» поставить на место «периода» и «состояние завершения» на место «состояния»:

1

 Александр Анатольевич

11.11.2009

В командировке

14.11.2009

Работает

 

1

 Александр Анатольевич

14.11.2009

Работает

   

В тексте запроса поле «ПЕРИОД» это можно вычислить так:

ВЫБОР
	КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода,ДЕНЬ)
			И СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
		ТОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения
	ИНАЧЕ СостояниеРаботниковОрганизаций.Период
КОНЕЦ

А поле «ПЕРИОД ЗАВЕРШЕНИЯ» следующим образом:

ВЫБОР
	КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода,ДЕНЬ)
			И СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
		ТОГДА ДАТАВРЕМЯ(1, 1, 1)
	ИНАЧЕ СостояниеРаботниковОрганизаций.ПериодЗавершения
КОНЕЦ

 

В последней строке поля «период завершения» и «состояние завершения»  не несут смысловой нагрузки, поскольку отчет по 31.12.2010.

11

 Александр Анатольевич

01.12.2010

В командировке

03.02.2011

Работает

 

11

 Александр Анатольевич

01.12.2010

В командировке

   

 

Текст третьего пакета:

ВЫБРАТЬ РАЗРЕШЕННЫЕ
	СостояниеРаботниковОрганизаций.Сотрудник КАК Сотрудник,
	СостояниеРаботниковОрганизаций.Организация КАК Организация,
	СостояниеРаботниковОрганизаций.Регистратор,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения
		ИНАЧЕ СостояниеРаботниковОрганизаций.Период
	КОНЕЦ КАК Период,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА СостояниеРаботниковОрганизаций.СостояниеЗавершения
		ИНАЧЕ СостояниеРаботниковОрганизаций.Состояние
	КОНЕЦ КАК Состояние,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА ДАТАВРЕМЯ(1, 1, 1)
		КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения > КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)
			ТОГДА ДАТАВРЕМЯ(1, 1, 1)
		ИНАЧЕ СостояниеРаботниковОрганизаций.ПериодЗавершения
	КОНЕЦ КАК ПериодЗавершения,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
		КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения > КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)
			ТОГДА ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
		ИНАЧЕ СостояниеРаботниковОрганизаций.СостояниеЗавершения
	КОНЕЦ КАК СостояниеЗавершения
ПОМЕСТИТЬ РС_СостоянияСотрудников
ИЗ
	РегистрСведений.СостояниеРаботниковОрганизаций КАК СостояниеРаботниковОрганизаций
ГДЕ
	СостояниеРаботниковОрганизаций.Сотрудник В
			(ВЫБРАТЬ
				ВТ.Сотрудник
			ИЗ
				ВТ_ТаблицаСотрудников КАК ВТ)
	И СостояниеРаботниковОрганизаций.Период > НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
	И СостояниеРаботниковОрганизаций.Период <= КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)
	И СостояниеРаботниковОрганизаций.Организация = &ПарамОрганизация

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

ВЫБРАТЬ
	СостояниеРаботниковОрганизацийСрезПоследних.Сотрудник,
	СостояниеРаботниковОрганизацийСрезПоследних.Организация,
	СостояниеРаботниковОрганизацийСрезПоследних.Регистратор,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения
		ИНАЧЕ СостояниеРаботниковОрганизацийСрезПоследних.Период
	КОНЕЦ,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА СостояниеРаботниковОрганизацийСрезПоследних.СостояниеЗавершения
		ИНАЧЕ СостояниеРаботниковОрганизацийСрезПоследних.Состояние
	КОНЕЦ,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА ДАТАВРЕМЯ(1, 1, 1)
		КОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения > КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)
			ТОГДА ДАТАВРЕМЯ(1, 1, 1)
		ИНАЧЕ СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения
	КОНЕЦ,
	ВЫБОР
		КОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения < НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
				И СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
			ТОГДА ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
		КОГДА СостояниеРаботниковОрганизацийСрезПоследних.ПериодЗавершения > КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)
			ТОГДА ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
		ИНАЧЕ СостояниеРаботниковОрганизацийСрезПоследних.СостояниеЗавершения
	КОНЕЦ
ИЗ
	РегистрСведений.СостояниеРаботниковОрганизаций.СрезПоследних(
			НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ),
			Сотрудник В
					(ВЫБРАТЬ
						ВТ.Сотрудник
					ИЗ
						ВТ_ТаблицаСотрудников КАК ВТ)
				И Организация = &ПарамОрганизация) КАК СостояниеРаботниковОрганизацийСрезПоследних

ИНДЕКСИРОВАТЬ ПО
	Сотрудник,
	Период,
	ПериодЗавершения,
	Организаци;

Количество полей.

7полей:  Сотрудник, Регистратор, Период ,Состояние, Организация,  ПериодЗавершения, СостояниеЗавершения.

 5 ссылочных, 2 примитивных.

Количество записей.

Строк при выводе результата в тестовой базе 50807 с отбором за 2011 год. 

5. Четвертый пакет: ВТ_СостоянияСотрудниковДополненные

Рассмотрим еще один возможный случай.

Записи регистра за период (01.01.2010-31.12.2010) с отбором по сотруднику:

           

№ п/п

Сотрудник

Период

Состояние

Дата возврата

Состояние по окончании

 

1

 Артем Михайлович

14.04.2010

Болеет

     

 

Первая запись в регистре о болезни, до этого строк нет.  Получается временной пробел за период 01.01.2010-13.04.2010. Если разобраться, то мы увидим, что сотрудник был принят 01.03.2010, но документ «Прием на работу в организацию» не делает проводок  по регистру состояний с состоянием «Работает». 

Или еще один пример. Сотрудник принят 07.08.2010 и с тех пор в базе не было введено по нему ни одного документа отклонения (очень трудолюбивый стахановец). Поскольку документ «Прием на работу в организацию» не делает проводок  по регистру состояний с состоянием «Работает» то нам нужно сделать это прямо в запросе вручную.

Документ «Увольнение из организации» так же не делает проводок по регистру состояний. В этой связи нам так же нужно обрабатывать такие случаи в запросе.

Для восполнения временного пробела нам нужно:

1)      выявить всех сотрудников, у которых нет ни одной записи с Периодом и ПериодомЗавершения (если он заполнен)

2)      для каждого сотрудника из 1) получить таблицу с полями: сотрудник, дата приема и состояние = «Работает» из регистра «Работники организаций».

3)      объединить полученные записи о приемах в организацию с записями временной таблицы РС_СостоянияСотрудников 2 пакета.

 

Текст четвертого пакета: 

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
	Вложенный.Сотрудник,
	Вложенный.Организация,
	Вложенный.Регистратор,
	Вложенный.Период,
	Вложенный.Состояние,
	Вложенный.ПериодЗавершения,
	Вложенный.СостояниеЗавершения
ПОМЕСТИТЬ ВТ_СостоянияСотрудниковДополненные
ИЗ
	(ВЫБРАТЬ
		РаботникиОрганизацийСрезПервых.Сотрудник КАК Сотрудник,
		РаботникиОрганизацийСрезПервых.Организация КАК Организация,
		РаботникиОрганизацийСрезПервых.Регистратор КАК Регистратор,
		РаботникиОрганизацийСрезПервых.Период КАК Период,
		ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.Работает) КАК Состояние,
		ДАТАВРЕМЯ(1, 1, 1) КАК ПериодЗавершения,
		ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка) КАК СостояниеЗавершения
	ИЗ
		РегистрСведений.РаботникиОрганизаций.СрезПервых(
				,
				Сотрудник В
						(ВЫБРАТЬ
							ВТ.Сотрудник
						ИЗ
							ВТ_ТаблицаСотрудников КАК ВТ)
					И ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.ПриемНаРаботу)
					И Организация = &ПарамОрганизация) КАК РаботникиОрганизацийСрезПервых
			ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
				РС_СостоянияСотрудников.Сотрудник КАК Сотрудник
			ИЗ
				РС_СостоянияСотрудников КАК РС_СостоянияСотрудников
					ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
						РС_СостоянияСотрудников.Сотрудник КАК Сотрудник
					ИЗ
						РС_СостоянияСотрудников КАК РС_СостоянияСотрудников
					ГДЕ
						ВЫБОР
								КОГДА РС_СостоянияСотрудников.ПериодЗавершения = ДАТАВРЕМЯ(1, 1, 1)
									ТОГДА РС_СостоянияСотрудников.Период <= НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
								ИНАЧЕ РС_СостоянияСотрудников.Период <= НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
										ИЛИ РС_СостоянияСотрудников.ПериодЗавершения <= НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ)
							КОНЕЦ
					
					СГРУППИРОВАТЬ ПО
						РС_СостоянияСотрудников.Сотрудник) КАК СотрудникиСЗаписямиНаПериодНачало
					ПО РС_СостоянияСотрудников.Сотрудник = СотрудникиСЗаписямиНаПериодНачало.Сотрудник
			ГДЕ
				СотрудникиСЗаписямиНаПериодНачало.Сотрудник ЕСТЬ NULL 
			
			СГРУППИРОВАТЬ ПО
				РС_СостоянияСотрудников.Сотрудник) КАК СотрудникиДляПоискаДатыПриема
			ПО РаботникиОрганизацийСрезПервых.Сотрудник = СотрудникиДляПоискаДатыПриема.Сотрудник
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		РС_СостоянияСотрудников.Сотрудник,
		РС_СостоянияСотрудников.Организация,
		РС_СостоянияСотрудников.Регистратор,
		РС_СостоянияСотрудников.Период,
		РС_СостоянияСотрудников.Состояние,
		РС_СостоянияСотрудников.ПериодЗавершения,
		РС_СостоянияСотрудников.СостояниеЗавершения
	ИЗ
		РС_СостоянияСотрудников КАК РС_СостоянияСотрудников
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		NULL,
		РаботникиОрганизацийСрезПервых.Организация,
		РаботникиОрганизацийСрезПервых.Регистратор,
		РаботникиОрганизацийСрезПервых.Период,
		ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.Работает),
		ДАТАВРЕМЯ(1, 1, 1),
		ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
	ИЗ
		РС_РаботникиОрганизаций КАК ВТ_ТаблицаСотрудников,
		РС_СостоянияСотрудников КАК РС_СостоянияСотрудников,
		РегистрСведений.РаботникиОрганизаций.СрезПервых(
				,
				Сотрудник В
						(ВЫБРАТЬ
							ВТ.Сотрудник
						ИЗ
							ВТ_ТаблицаСотрудников КАК ВТ)
					И ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.ПриемНаРаботу)
					И Организация = &ПарамОрганизация) КАК РаботникиОрганизацийСрезПервых
	ГДЕ
		РС_СостоянияСотрудников.Сотрудник ЕСТЬ NULL 
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		РаботникиОрганизаций.Сотрудник,
		РаботникиОрганизаций.Организация,
		РаботникиОрганизаций.Регистратор,
		РаботникиОрганизаций.Период,
		ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.НеРаботает),
		ДАТАВРЕМЯ(1, 1, 1),
		ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
	ИЗ
		РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
	ГДЕ
		РаботникиОрганизаций.Регистратор ССЫЛКА Документ.УвольнениеИзОрганизаций
		И РаботникиОрганизаций.Период МЕЖДУ НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ) И КОНЕЦПЕРИОДА(&ОкончаниеПериода, ДЕНЬ)) КАК Вложенный

ИНДЕКСИРОВАТЬ ПО
	Вложенный.Сотрудник,
	Вложенный.Период,
	Вложенный.ПериодЗавершения;

Количество полей.

7полей:  Сотрудник, Организация, Регистратор, Период, Состояние, ПериодЗавершения , СостояниеЗавершения.

Из них 5 ссылочных, 2 примитивных.

 Количество записей. 

Строк при выводе результата в тестовой базе 6074 с отбором за 2011 год. 

6. Пятый пакет: ВТ_СостоянияСУчетомПересеченийПериодов 

Рассмотрим случаи пересечения периодов. 

Записи регистра за период (01.01.2010-31.12.2010) с отбором по сотруднику:

           
             

№ п/п

Сотрудник

Период

Состояние

Период завершения

Состояние завершения

Регистратор

 

13

 Анатолий Борисович

01.01.2010

В ежегодном отпуске

23.01.2010

Работает

Отпуска организаций 1910-ОТ от 22.12.2009 0:00:00

 

14

 Анатолий Борисович

15.01.2010

В отпуске без сохранения зарплаты

25.03.2010

Работает

Отпуска организаций 45-ОБ от 23.03.2010 10:39:34

 
                         

При наличии таких записей отчет нам должен четко показать следующую информацию:

С 01.01 по 14.01 – ежегодный отпуск

С 15.01 по 25.03 – отпуск без сохранения

Другими словами нам нужно:

1)      найти все записи, для которых существуют другие записи, разрывающие их периоды или совпадающие с ними

2)      в найденных записях вычислить ПериодЗавершения=Дата(1,1,1) и СостояниеЗавершения=ПустаяСсылка 

Текст пятого пакета:

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Вложенный.Сотрудник КАК Сотрудник,
	Вложенный.Организация КАК Организация,
	Вложенный.Регистратор КАК Регистратор,
	Вложенный.Период КАК Период,
	Вложенный.Состояние КАК Состояние
ПОМЕСТИТЬ ВТ_СостоянияСУчетомПересеченийПериодов
ИЗ
	(ВЫБРАТЬ РАЗЛИЧНЫЕ
		ВТ_СостоянияСотрудниковДополненные1.Сотрудник КАК Сотрудник,
		ВТ_СостоянияСотрудниковДополненные1.Организация КАК Организация,
		ВТ_СостоянияСотрудниковДополненные1.Регистратор КАК Регистратор,
		ВЫБОР
			КОГДА ВТ_СостоянияСотрудниковДополненные2.Сотрудник ЕСТЬ NULL 
				ТОГДА ВТ_СостоянияСотрудниковДополненные1.ПериодЗавершения
			ИНАЧЕ ДАТАВРЕМЯ(1, 1, 1)
		КОНЕЦ КАК Период,
		ВЫБОР
			КОГДА ВТ_СостоянияСотрудниковДополненные2.Сотрудник ЕСТЬ NULL 
				ТОГДА ВТ_СостоянияСотрудниковДополненные1.СостояниеЗавершения
			ИНАЧЕ ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
		КОНЕЦ КАК Состояние
	ИЗ
		ВТ_СостоянияСотрудниковДополненные КАК ВТ_СостоянияСотрудниковДополненные1
			ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СостоянияСотрудниковДополненные КАК ВТ_СостоянияСотрудниковДополненные2
			ПО ВТ_СостоянияСотрудниковДополненные1.Сотрудник = ВТ_СостоянияСотрудниковДополненные2.Сотрудник
				И (ВТ_СостоянияСотрудниковДополненные1.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1))
				И (ВТ_СостоянияСотрудниковДополненные2.Период > ВТ_СостоянияСотрудниковДополненные1.Период)
				И (ВТ_СостоянияСотрудниковДополненные2.Период <= ВТ_СостоянияСотрудниковДополненные1.ПериодЗавершения)
				И ВТ_СостоянияСотрудниковДополненные1.Организация = ВТ_СостоянияСотрудниковДополненные2.Организация
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		ВТ_СостоянияСотрудниковДополненные.Сотрудник,
		ВТ_СостоянияСотрудниковДополненные.Организация,
		ВТ_СостоянияСотрудниковДополненные.Регистратор,
		ВТ_СостоянияСотрудниковДополненные.Период,
		ВТ_СостоянияСотрудниковДополненные.Состояние
	ИЗ
		ВТ_СостоянияСотрудниковДополненные КАК ВТ_СостоянияСотрудниковДополненные) КАК Вложенный
ГДЕ
	(НЕ Вложенный.Период = ДАТАВРЕМЯ(1, 1, 1))

ИНДЕКСИРОВАТЬ ПО
	Сотрудник,
	Период;
 

Количество полей.

5полей:  Сотрудник, Организация, Регистратор, Период, Состояние

3 ссылочных, 2 примитивных. 

Количество записей.

Строк при выводе результата в тестовой базе 9493 с отбором за 2011 год. 

7. Шестой пакет: ВТ_СостоянияРазвернутые

Получим из 1 записи 2 записи,  будто «разворачивая» их. Например из 1записи:

№ п/п

Сотрудник

Период

Состояние

Период завершения

Состояние завершения

Регистратор

13

 Анатолий Борисович

11.01.2010

В ежегодном отпуске

23.01.2010

Работает

Отпуска организаций 1910-ОТ от 22.12.2009 0:00:00

 

получим 2 записи:

№ п/п

Сотрудник

Период

Состояние

Регистратор

13

 Анатолий Борисович

11.01.2010

В ежегодном отпуске

Отпуска организаций 1910-ОТ от 22.12.2009 0:00:00

14

 Анатолий Борисович

23.01.2010

Работает

Отпуска организаций 1910-ОТ от 22.12.2009 0:00:00

Количество записей получится не ровно в 2 раза больше, т.к. будет еще условие.

Текст шестого пакета:

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Состояния.Регистратор КАК РегистраторСостояния,
	ВЫБОР
		КОГДА Состояния.Регистратор ССЫЛКА Документ.ВозвратНаРаботуОрганизаций
			ТОГДА "Возврат на работу"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.ИзменениеУсловийОплатыОтпускаПоУходуЗаРебенком
			ТОГДА "Изменение условий оплаты отпуска по уходу"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.КадровоеПеремещениеОрганизаций
			ТОГДА "Кадровое перемещение"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.КомандировкиОрганизаций
			ТОГДА "Командировка"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.НеявкиИБолезниОрганизаций
			ТОГДА "Неявки и болезни"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.ОтпускаОрганизаций
			ТОГДА "Отпуск"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.ОтпускПоУходуЗаРебенком
			ТОГДА "Отпуск по уходу"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.ПриемНаРаботуВОрганизацию
			ТОГДА "Прием на работу"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.УвольнениеИзОрганизаций
			ТОГДА "Увольнение"
		КОГДА Состояния.Регистратор ССЫЛКА Документ.ПереносДанных
			ТОГДА "Перенос данных"
		ИНАЧЕ "Прочее"
	КОНЕЦ КАК РегистраторСостоянияВид,
	Состояния.Организация КАК Организация,
	Состояния.Сотрудник КАК Сотрудник,
	Состояния.ПериодС КАК ПериодС,
	Состояния.ПериодПо КАК ПериодПо,
	Состояния.Состояние КАК Состояние,
	ВЫБОР
		КОГДА Состояния.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.НеРаботает)
			ТОГДА 0
		ИНАЧЕ РАЗНОСТЬДАТ(Состояния.ПериодС, Состояния.ПериодПо, ДЕНЬ) + 1
	КОНЕЦ КАК ДнейОтклонения,
	ВЫБОР
		КОГДА Состояния.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.НеРаботает)
			ТОГДА 0
		ИНАЧЕ ВЫБОР
				КОГДА Состояния.ПериодС < &НачалоПериода
						И Состояния.ПериодПо > &ОкончаниеПериода
					ТОГДА РАЗНОСТЬДАТ(&НачалоПериода, &ОкончаниеПериода, ДЕНЬ) + 1
				КОГДА Состояния.ПериодС < &НачалоПериода
						И Состояния.ПериодПо <= &ОкончаниеПериода
					ТОГДА РАЗНОСТЬДАТ(&НачалоПериода, Состояния.ПериодПо, ДЕНЬ) + 1
				КОГДА Состояния.ПериодС >= &НачалоПериода
						И Состояния.ПериодПо > &ОкончаниеПериода
					ТОГДА РАЗНОСТЬДАТ(Состояния.ПериодС, &ОкончаниеПериода, ДЕНЬ) + 1
				ИНАЧЕ РАЗНОСТЬДАТ(Состояния.ПериодС, Состояния.ПериодПо, ДЕНЬ) + 1
			КОНЕЦ
	КОНЕЦ КАК ДнейВПериоде
ПОМЕСТИТЬ ВТ_СостоянияРазвернутые
ИЗ
	(ВЫБРАТЬ
		ВТ_СостоянияСУчетомПересеченийПериодов.Сотрудник КАК Сотрудник,
		ВТ_СостоянияСУчетомПересеченийПериодов.Организация КАК Организация,
		ВТ_СостоянияСУчетомПересеченийПериодов.Регистратор КАК Регистратор,
		ВТ_СостоянияСУчетомПересеченийПериодов.Период КАК ПериодС,
		ВЫБОР
			КОГДА ВТ_СостоянияСУчетомПересеченийПериодов.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.НеРаботает)
				ТОГДА ВТ_СостоянияСУчетомПересеченийПериодов.Период
			ИНАЧЕ ЕСТЬNULL(ДОБАВИТЬКДАТЕ(Тета.ПериодСнизу, ДЕНЬ, -1), &ОкончаниеПериода)
		КОНЕЦ КАК ПериодПо,
		ВТ_СостоянияСУчетомПересеченийПериодов.Состояние КАК Состояние
	ИЗ
		ВТ_СостоянияСУчетомПересеченийПериодов КАК ВТ_СостоянияСУчетомПересеченийПериодов
			ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
				ВТ_СостоянияСУчетомПересеченийПериодов.Сотрудник КАК Сотрудник,
				ВТ_СостоянияСУчетомПересеченийПериодов.Организация КАК Организация,
				ВТ_СостоянияСУчетомПересеченийПериодов.Период КАК Период,
				МИНИМУМ(ВТ_СостоянияСУчетомПересеченийПериодовСнизу.Период) КАК ПериодСнизу
			ИЗ
				ВТ_СостоянияСУчетомПересеченийПериодов КАК ВТ_СостоянияСУчетомПересеченийПериодов
					ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СостоянияСУчетомПересеченийПериодов КАК ВТ_СостоянияСУчетомПересеченийПериодовСнизу
					ПО ВТ_СостоянияСУчетомПересеченийПериодов.Сотрудник = ВТ_СостоянияСУчетомПересеченийПериодовСнизу.Сотрудник
						И ВТ_СостоянияСУчетомПересеченийПериодов.Организация = ВТ_СостоянияСУчетомПересеченийПериодовСнизу.Организация
						И ВТ_СостоянияСУчетомПересеченийПериодов.Период < ВТ_СостоянияСУчетомПересеченийПериодовСнизу.Период
			
			СГРУППИРОВАТЬ ПО
				ВТ_СостоянияСУчетомПересеченийПериодов.Сотрудник,
				ВТ_СостоянияСУчетомПересеченийПериодов.Организация,
				ВТ_СостоянияСУчетомПересеченийПериодов.Период) КАК Тета
			ПО ВТ_СостоянияСУчетомПересеченийПериодов.Сотрудник = Тета.Сотрудник
				И ВТ_СостоянияСУчетомПересеченийПериодов.Организация = Тета.Организация
				И ВТ_СостоянияСУчетомПересеченийПериодов.Период = Тета.Период) КАК Состояния

ИНДЕКСИРОВАТЬ ПО Сотрудник, ПериодС, ПериодПо; 
 

Количество полей.

9полей:  Сотрудник, Организация, РегистраторСостояния, РегистраторСостоянияВид, ПериодС, ПериодПо, Состояние, ДнейОтклонения, ДнейВПериоде .

Из них 5 ссылочных, 4 примитивных.

Количество записей. 

Строк при выводе результата в тестовой базе 9493  за 2011 год. 

Оптимизация.

Пятый «ВТ_СостоянияСУчетомПересеченийПериодов» и шестой «ВТ_СостоянияРазвернутые
пакеты можно без потери производительности объединить в один пакет. 
Выше они специально разделены для более простого понимания того, что происходит.  Оптимизированный пакет «ВТ_СостоянияРазвернутые» будет выглядеть вот так:

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Вложенный.Сотрудник,
	Вложенный.Организация,
	Вложенный.Регистратор,
	Вложенный.Период,
	Вложенный.Состояние
ПОМЕСТИТЬ ВТ_Развернутые
ИЗ
	(ВЫБРАТЬ РАЗЛИЧНЫЕ
		ВТ_СостоянияСотрудниковДополненные1.Сотрудник КАК Сотрудник,
		ВТ_СостоянияСотрудниковДополненные1.Организация КАК Организация,
		ВТ_СостоянияСотрудниковДополненные1.Регистратор КАК Регистратор,
		ВЫБОР
			КОГДА ВТ_СостоянияСотрудниковДополненные2.Сотрудник ЕСТЬ NULL 
				ТОГДА ВТ_СостоянияСотрудниковДополненные1.ПериодЗавершения
			ИНАЧЕ ДАТАВРЕМЯ(1, 1, 1)
		КОНЕЦ КАК Период,
		ВЫБОР
			КОГДА ВТ_СостоянияСотрудниковДополненные2.Сотрудник ЕСТЬ NULL 
				ТОГДА ВТ_СостоянияСотрудниковДополненные1.СостояниеЗавершения
			ИНАЧЕ ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)
		КОНЕЦ КАК Состояние
	ИЗ
		ВТ_СостоянияСотрудниковДополненные КАК ВТ_СостоянияСотрудниковДополненные1
			ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СостоянияСотрудниковДополненные КАК ВТ_СостоянияСотрудниковДополненные2
			ПО ВТ_СостоянияСотрудниковДополненные1.Сотрудник = ВТ_СостоянияСотрудниковДополненные2.Сотрудник
				И (ВТ_СостоянияСотрудниковДополненные1.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1))
				И (ВТ_СостоянияСотрудниковДополненные2.Период > ВТ_СостоянияСотрудниковДополненные1.Период)
				И (ВТ_СостоянияСотрудниковДополненные2.Период <= ВТ_СостоянияСотрудниковДополненные1.ПериодЗавершения)
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		ВТ_СостоянияСотрудниковДополненные.Сотрудник,
		ВТ_СостоянияСотрудниковДополненные.Организация,
		ВТ_СостоянияСотрудниковДополненные.Регистратор,
		ВТ_СостоянияСотрудниковДополненные.Период,
		ВТ_СостоянияСотрудниковДополненные.Состояние
	ИЗ
		ВТ_СостоянияСотрудниковДополненные КАК ВТ_СостоянияСотрудниковДополненные) КАК Вложенный
ГДЕ
	(НЕ Вложенный.Период = ДАТАВРЕМЯ(1, 1, 1));

8. Седьмой пакет: ВТ_СверткаПоследовательныхОдинаковыхЗаписейСостояний

В полученной таблице можно найти следующие записи:

 

Вячеслав

Работает

03.09.2011

05.09.2011

Вячеслав

Болеет

06.09.2011

07.09.2011

Вячеслав

Болеет

08.09.2011

03.10.2011

Вячеслав

Болеет

04.10.2011

19.10.2011

Вячеслав

Работает

20.10.2011

31.12.2011

 

Три записи о состоянии «болеет» можно и  нужно объединить в одну.

 

Получим следующую таблицу : 

Вячеслав

Работает

03.09.2011

05.09.2011

Вячеслав

Болеет

06.09.2011

07.09.2011

Вячеслав

Работает

20.10.2011

31.12.2011

 
 

Теперь  нужно не забыть увеличить  «ПериодПо» в оставшейся записи на число дней удаленных записей.

 

В результате получим следующую таблицу:

 

Вячеслав

Работает

03.09.2011

05.09.2011

Вячеслав

Болеет

06.09.2011

19.09.2011

Вячеслав

Работает

20.10.2011

31.12.2011

 

 

 

Текст седьмого пакета:

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ_СостоянияРазвернутые.РегистраторСостояния,
	ВТ_СостоянияРазвернутые.РегистраторСостоянияВид,
	ВТ_СостоянияРазвернутые.Организация,
	ВТ_СостоянияРазвернутые.Сотрудник КАК Сотрудник,
	ВТ_СостоянияРазвернутые.ПериодС КАК ПериодС,
	ВТ_СостоянияРазвернутые.ПериодПо КАК ПериодПо,
	ВТ_СостоянияРазвернутые.Состояние,
	ВТ_СостоянияРазвернутые.ДнейОтклонения,
	ВТ_СостоянияРазвернутые.ДнейВПериоде
ПОМЕСТИТЬ ВТ_СверткаПоследовательныхОдинаковыхЗаписейСостояний
ИЗ
	ВТ_СостоянияРазвернутые КАК ВТ_СостоянияРазвернутые
		ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
			ВТ_СостоянияРазвернутые.РегистраторСостояния КАК РегистраторСостояния_ПредЗапись,
			ВТ_СостоянияРазвернутые.РегистраторСостоянияВид КАК РегистраторСостоянияВид_ПредЗапись,
			ВТ_СостоянияРазвернутые.Организация КАК Организация_ПредЗапись,
			ВТ_СостоянияРазвернутые.Сотрудник КАК Сотрудник_ПредЗапись,
			ВТ_СостоянияРазвернутые.ПериодС КАК ПериодС_ПредЗапись,
			ВТ_СостоянияРазвернутые.ПериодПо КАК ПериодПо_ПредЗапись,
			ВТ_СостоянияРазвернутые.Состояние КАК Состояние_ПредЗапись,
			ВТ_СостоянияРазвернутые.ДнейОтклонения КАК ДнейОтклонения_ПредЗапись,
			ВТ_СостоянияРазвернутые.ДнейВПериоде КАК ДнейВПериоде_ПредЗапись,
			ТЕТА.ПериодС КАК ПериодС
		ИЗ
			(ВЫБРАТЬ
				ВТ_СостоянияРазвернутые.Сотрудник КАК Сотрудник,
				ВТ_СостоянияРазвернутые.ПериодС КАК ПериодС,
				МАКСИМУМ(ВТ_СостоянияРазвернутые_ПредЗапись.ПериодС) КАК ПериодС_ПредЗапись
			ИЗ
				ВТ_СостоянияРазвернутые КАК ВТ_СостоянияРазвернутые
					ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СостоянияРазвернутые КАК ВТ_СостоянияРазвернутые_ПредЗапись
					ПО ВТ_СостоянияРазвернутые.Сотрудник = ВТ_СостоянияРазвернутые_ПредЗапись.Сотрудник
						И ВТ_СостоянияРазвернутые.ПериодС > ВТ_СостоянияРазвернутые_ПредЗапись.ПериодС
			
			СГРУППИРОВАТЬ ПО
				ВТ_СостоянияРазвернутые.Сотрудник,
				ВТ_СостоянияРазвернутые.ПериодС) КАК ТЕТА
				ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СостоянияРазвернутые КАК ВТ_СостоянияРазвернутые
				ПО ТЕТА.Сотрудник = ВТ_СостоянияРазвернутые.Сотрудник
					И ТЕТА.ПериодС_ПредЗапись = ВТ_СостоянияРазвернутые.ПериодС) КАК ПредСостояние
		ПО ВТ_СостоянияРазвернутые.Сотрудник = ПредСостояние.Сотрудник_ПредЗапись
			И ВТ_СостоянияРазвернутые.ПериодС = ПредСостояние.ПериодС
ГДЕ
	(НЕ ЕСТЬNULL(ПредСостояние.Состояние_ПредЗапись, ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.ПустаяСсылка)) = ВТ_СостоянияРазвернутые.Состояние)

ИНДЕКСИРОВАТЬ ПО
	Сотрудник,
	ПериодС,
	ПериодПо;

Количество полей.

9полей:  Сотрудник, Организация, РегистраторСостояния, РегистраторСостоянияВид, ПериодС, ПериодПо, Состояние, ДнейОтклонения, ДнейВПериоде .

Из них 5 ссылочных, 4 примитивных.

Количество записей. 

Строк при выводе результата в тестовой базе 9056  за 2011 год.

 

9. Результирующий пакет

Текст результирующего пакета:

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВЛОЖЕННЫЙ.РегистраторСостояния,
	ВЛОЖЕННЫЙ.РегистраторСостоянияВид,
	ВЛОЖЕННЫЙ.Организация,
	ВЛОЖЕННЫЙ.Сотрудник,
	ВЛОЖЕННЫЙ.ПериодС,
	ВЛОЖЕННЫЙ.ПериодПо,
	ВЛОЖЕННЫЙ.Состояние,
	ВЫБОР
		КОГДА ВЛОЖЕННЫЙ.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.НеРаботает)
			ТОГДА 0
		ИНАЧЕ РАЗНОСТЬДАТ(ВЛОЖЕННЫЙ.ПериодС, ВЛОЖЕННЫЙ.ПериодПо, ДЕНЬ) + 1
	КОНЕЦ КАК ДнейОтклонения,
	ВЫБОР
		КОГДА ВЛОЖЕННЫЙ.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияРаботникаОрганизации.НеРаботает)
			ТОГДА 0
		ИНАЧЕ ВЫБОР
				КОГДА ВЛОЖЕННЫЙ.ПериодС < &НачалоПериода
						И ВЛОЖЕННЫЙ.ПериодПо > &ОкончаниеПериода
					ТОГДА РАЗНОСТЬДАТ(&НачалоПериода, &ОкончаниеПериода, ДЕНЬ) + 1
				КОГДА ВЛОЖЕННЫЙ.ПериодС < &НачалоПериода
						И ВЛОЖЕННЫЙ.ПериодПо <= &ОкончаниеПериода
					ТОГДА РАЗНОСТЬДАТ(&НачалоПериода, ВЛОЖЕННЫЙ.ПериодПо, ДЕНЬ) + 1
				КОГДА ВЛОЖЕННЫЙ.ПериодС >= &НачалоПериода
						И ВЛОЖЕННЫЙ.ПериодПо > &ОкончаниеПериода
					ТОГДА РАЗНОСТЬДАТ(ВЛОЖЕННЫЙ.ПериодС, &ОкончаниеПериода, ДЕНЬ) + 1
				ИНАЧЕ РАЗНОСТЬДАТ(ВЛОЖЕННЫЙ.ПериодС, ВЛОЖЕННЫЙ.ПериодПо, ДЕНЬ) + 1
			КОНЕЦ
	КОНЕЦ КАК ДнейВПериоде
ИЗ
	(ВЫБРАТЬ
		ВТ_Свертка.РегистраторСостояния КАК РегистраторСостояния,
		ВТ_Свертка.РегистраторСостоянияВид КАК РегистраторСостоянияВид,
		ВТ_Свертка.Организация КАК Организация,
		ВТ_Свертка.Сотрудник КАК Сотрудник,
		ВТ_Свертка.ПериодС КАК ПериодС,
		ВЫБОР
			КОГДА СледЗапись.ПериодС_СледЗапись ЕСТЬ NULL 
				ТОГДА ВТ_Свертка.ПериодПо
			КОГДА ДОБАВИТЬКДАТЕ(СледЗапись.ПериодС_СледЗапись, ДЕНЬ, -1) = ВТ_Свертка.ПериодПо
				ТОГДА ВТ_Свертка.ПериодПо
			ИНАЧЕ ДОБАВИТЬКДАТЕ(ЕСТЬNULL(СледЗапись.ПериодС_СледЗапись, ДАТАВРЕМЯ(2011, 1, 1)), ДЕНЬ, -1)
		КОНЕЦ КАК ПериодПо,
		ВТ_Свертка.Состояние КАК Состояние,
		ВТ_Свертка.ДнейОтклонения КАК ДнейОтклонения,
		ВТ_Свертка.ДнейВПериоде КАК ДнейВПериоде,
		СледЗапись.ПериодС_СледЗапись КАК ПериодС_СледЗапись
	ИЗ
		ВТ_СверткаПоследовательныхОдинаковыхЗаписейСостояний КАК ВТ_Свертка
			ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
				ВТ_Свертка.РегистраторСостояния КАК РегистраторСостояния_СледЗапись,
				ВТ_Свертка.РегистраторСостоянияВид КАК РегистраторСостоянияВид_СледЗапись,
				ВТ_Свертка.Организация КАК Организация_СледЗапись,
				ВТ_Свертка.Сотрудник КАК Сотрудник_СледЗапись,
				ВТ_Свертка.ПериодС КАК ПериодС_СледЗапись,
				ВТ_Свертка.ПериодПо КАК ПериодПо_СледЗапись,
				ВТ_Свертка.Состояние КАК Состояние_СледЗапись,
				ВТ_Свертка.ДнейОтклонения КАК ДнейОтклонения_СледЗапись,
				ВТ_Свертка.ДнейВПериоде КАК ДнейВПериоде_СледЗапись,
				ТЕТА.ПериодС КАК ПериодС
			ИЗ
				(ВЫБРАТЬ
					ВТ_Свертка.Сотрудник КАК Сотрудник,
					ВТ_Свертка.ПериодС КАК ПериодС,
					МИНИМУМ(ВТ_Свертка_СледЗапись.ПериодС) КАК ПериодС_СледЗапись
				ИЗ
					ВТ_СверткаПоследовательныхОдинаковыхЗаписейСостояний КАК ВТ_Свертка
						ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СверткаПоследовательныхОдинаковыхЗаписейСостояний КАК ВТ_Свертка_СледЗапись
						ПО ВТ_Свертка.Сотрудник = ВТ_Свертка_СледЗапись.Сотрудник
							И ВТ_Свертка.ПериодС < ВТ_Свертка_СледЗапись.ПериодС
				
				СГРУППИРОВАТЬ ПО
					ВТ_Свертка.Сотрудник,
					ВТ_Свертка.ПериодС) КАК ТЕТА
					ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СверткаПоследовательныхОдинаковыхЗаписейСостояний КАК ВТ_Свертка
					ПО ТЕТА.Сотрудник = ВТ_Свертка.Сотрудник
						И ТЕТА.ПериодС_СледЗапись = ВТ_Свертка.ПериодС) КАК СледЗапись
			ПО ВТ_Свертка.Сотрудник = СледЗапись.Сотрудник_СледЗапись
				И ВТ_Свертка.ПериодС = СледЗапись.ПериодС) КАК ВЛОЖЕННЫЙ

Количество полей.

9полей:  Сотрудник, Организация, РегистраторСостояния, РегистраторСостоянияВид, ПериодС, ПериодПо, Состояние, ДнейОтклонения, ДнейВПериоде .

Из них 5 ссылочных, 4 примитивных.

Количество записей.

Строк при выводе результата в тестовой базе 9056  за 2011 год.

Нужно понимать, что это полная информация о состояниях более чем 1 тысячи сотрудников за 2011 год.

Полученная таблица является развернутой и наиболее полной информацией о состояниях (отклонениях) сотрудниках за выбранный период. В чистом виде данный запрос рекомендую использовать для создания отчетов, где используется записи регистра сведений «СостояниеРаботниковОрганизаций».

 

10. Использование индексов и индексирования.

Давайте сделаем замер производительности запроса на получения записей за  период с 01.01.209 по 31.12.2011 год. Сначала будем тестировать на типовой конфигурации ЗУП 2.5.37.1, а затем на измененной, с установленным свойством «индексировать» в измерении «Сотрудник». Запускать запрос будем из обработки «Консоль отчетов». Сортируем по времени выполнения и видим строку №389  Обработка.КонсольОтчетов.Форма :

МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанныхКонсоли, ИсполняемыеНастройки, ДанныеРасшифровкиКонсоли);

- это строка и будет нашей лакмусовой бумажкой.

База файловая размером 3,27 Гб, ПК : intel(r) i5 3.33 Ггц, ОЗУ 4 Гб, 32 разрядная ОС Win7.

Замеры делались 20 раз, с предварительной чисткой КЭШа. Таблица усредненных результатов:

Типовая конфигурация

Измененная конфигурация с индексированным полем «Сотрудник»

Кол

Время %

Время

Кол

Время %

Время

1

0,1745

1,91

1

0,1636

1,76

Замеры показывают, что установка свойства «индексировать» у измерения «Сотрудник» регистров сведений «СостояниеРаботниковОрганизаций» и «РаботникиОрганизаций», дает небольшой прирост производительности.  Расплата за производительность – сложности при обновлении конфигурации (а если она типовая, то снятие с поддержки).

 

 

Обновления, изменения, доработки по просьбам трудящихся.

Дата: 20120904. По просьбе пользователя rasswet поясняю:
дней в периоде - это сколько дней неявки приходится на выбранный в параметрах отчета период.
дней отклонения - это общее зарегистрированное в программе число дней неявки.
Например, строим отчет за период с 01 по 31 января 2012 года. Сотрудница 15 декабря 2011 года уходит в отпуск по уходу за ребенком до 2013 года. Тогда=31, а=547.

Дата: 20120907.  Новая версия отчета. Исправлены все выявленные ошибки и частные случаи с комбинацией различных отклонений. Отчет тестировался в ЗУП 2.5.54.1 на платформе 8.2.15.310.

Дата: 20120908.  Описание отчета поделено на 2 смысловые части: для пользователя (в начале статьи) и для разработчика. В пользовательской части добавлено несколько картинок с примерами настроек отчета.

Файлы обработки:

-