Многократное изменение значения в периоде (запрос)

24.10.23

Разработка - Запросы

При решении задач расчетов, а также и в других разделах учета (оперативный, бухгалтерский) встречается проблема многократного изменения значения в периоде. Рассмотрим простую задачу: Все сотрудники предприятия работают по пятидневному графику работы, совместительство не допускается. Сотрудники предприятия получают оплату по окладу пропорционально отработанному времени в днях. Дневная ставка рассчитывается как начальное значение оклада, деленное на количество рабочих дней в том же периоде, что и фактически отработанные дни. В течение расчетного периода первоначальное значение оклада может быть неоднократно изменено. В информационной базе необходимо хранить историю его изменения. Расчет должен проводиться исходя из действующего на рассчитываемую дату начального значения оклада. Например, если начальное значение оклада изменилось 5 августа, то до 5 августа при расчете берется старое значение, а начиная с 5 августа – новое, и. т. д.

Скачать исходный код

Наименование Файл Версия Размер
Многократное изменение значения в периоде (запрос):
.dt 134,25Kb
0
.dt 134,25Kb Скачать

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

Исходные данные:

1. Документ начисления по окладу:

 

 

Ниже данные периодического регистра сведений с периодичностью день, в котором мы храним первоначальное значение оклада:

 

 

Итоговые интервалы со значением оклада у нас будут выглядеть так:

Сотрудник Дата начала  Дата окончания  Размер
Иванов 05.09.2023  06.09.2023  250,00
Иванов 07.09.2023  10.09.2023  200,00
Иванов 11.09.2023  14.09.2023  100,00
Иванов 15.09.2023  20.09.2023  150,00
Иванов 21.09.2023  24.09.2023  400,00
Иванов 25.09.2023  26.09.2023  300,00
Иванов 27.09.2023  28.09.2023  200,00
Петров 01.09.2023  06.09.2023  1 000,00
Петров 07.09.2023  12.09.2023  2 000,00
Петров 13.09.2023  20.09.2023  3 000,00
Петров 21.09.2023  25.09.2023  4 000,00
Петров 26.09.2023  30.09.2023  5 000,00

 

Эти итоговые данные мы должны получить запросом и рассчитать зарплату по окладу для нашим сотрудников:

 

 

План запроса:

1. объединяем срез последних РС на дату регистрации и записи РС с отбором внутри нашего месяца начисления, помещаем во временную таблицу, индексируем по Сотруднику и периоду.

2. полученную временную таблицу пронумеруем по порядку, порядок должен быть Сотрудник, Период, пронумерованную таблицу поместим во временную (таким образом можно пронумеровать только временную таблицу)

3. полученную таблицу соединяем саму с собой по сотруднику и по номеру строки со сдвигом номера на единицу, тем самым получая начало и окончания интервала. Одновременно, для конца интервала отнимаем день, а те записи которые по сотруднику не сошлись - устанавливаем для них конец периода = концу месяца регистрации, помещаем во временную таблицу

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

Готово.

3,4 пункты покажутся сначала не очень понятными, но если попробовать покрутить запрос в консоле станет понятнее.

Нужно просто представить что пронумерованную таблицу регистра мы сдвигаем на строку вверх чтобы получить дату окончания, и моя мысль станет более понятной:

      Период
Сотрудник Оклад Период 29.08.2023
Иванов 200,00 29.08.2023 01.09.2023
Иванов 300,00 01.09.2023 04.09.2023
Иванов 250,00 04.09.2023 07.09.2023
Иванов 200,00 07.09.2023 11.09.2023
Иванов 100,00 11.09.2023 15.09.2023
Иванов 150,00 15.09.2023 21.09.2023
Иванов 400,00 21.09.2023 25.09.2023
Иванов 300,00 25.09.2023 27.09.2023
Иванов 200,00 27.09.2023 29.09.2023
Иванов 500,00 29.09.2023 01.08.2023
Петров 1 000,00 01.08.2023 07.09.2023
Петров 2 000,00 07.09.2023 13.09.2023
Петров 3 000,00 13.09.2023 21.09.2023
Петров 4 000,00 21.09.2023 26.09.2023
Петров 5 000,00 26.09.2023  
       
    это период начала Это период окончания - здесь сдвинули наверх на одну строку и отняли день, чтобы получить конец интервала, а если дата получилась пустая, то добавили месяц к периоду регистрации и тоже отняли день

 

Запрос будет выглядеть следующим образом:

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

Тестирование проводилось на платформе 8.3.18.1289.

Запрос конфигурация значение в периоде расчет

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    127447    688    389    

740

Пропорциональное распределение в запросе с использованием АвтоНомерЗаписи()

Запросы Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    2444    andrey_sag    10    

29

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    6122    KawaNoNeko    23    

26

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2204    2    Yashazz    0    

31

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6812    32    mkalimulin    31    

53

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1952    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5700    user1923546    26    

46

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16764    skovpin_sa    14    

101
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. tormozit 7146 24.10.23 10:29 Сейчас в теме
Чтобы гарантировать правильтный порядок "АВТОНОМЕРЗАПИСИ() КАК НомерСтроки", нужно добавить ПЕРВЫЕ 10000000 и УПОРЯДОЧИТЬ. https://github.com/SeiOkami/OneS/issues/268
2. malinapc 25.10.23 10:46 Сейчас в теме
(1)
Комментарии

Нам главное получить номера строк без дублей, чтобы связать таблицу саму с собой по номерстроки = номерстроки-1, так что это видимо не проблема
3. Gesperid 2 01.11.23 12:00 Сейчас в теме
Во-первых
ДОБАВИТЬКДАТЕ(ДОБАВИТЬКДАТЕ(&ПериодРегистрации, МЕСЯЦ, 1), СЕКУНДА, -1)
можно заменить на
КОНЕЦПЕРИОДА(&ПериодРегистрации, МЕСЯЦ)

Во-вторых получить интервалы по списку дат можно без нумерации.
ВЫБРАТЬ
	ДатыС.Измерения КАК Измерения,
	ДатыС.ДополнительныеПоля КАК ДополнительныеПоля,
	ДатыС.ИмяПоляДата КАК ДатаС,
	ЕСТЬNULL(МИНИМУМ(ДатыДо.ИмяПоляДата), ДАТАВРЕМЯ(3999, 12, 31, 23, 59, 59)) КАК ДатаДо
ПОМЕСТИТЬ ВТИнтервалы
ИЗ
	втДаты КАК ДатыС
		ЛЕВОЕ СОЕДИНЕНИЕ втДаты КАК ДатыДо
		ПО ДатыС.Измерения = ДатыДо.Измерения
			И ДатыС.ИмяПоляДата < ДатыДо.ИмяПоляДата

СГРУППИРОВАТЬ ПО
	ДатыС.ИмяПоляДата,
	ДатыС.ДополнительныеПоля,
	ДатыС.Измерения
Показать

см. https://its.1c.ru/db/metod81#content:2910:hdoc, типовые и публикации на ИС.
4. malinapc 14.11.23 23:08 Сейчас в теме
1. Совершенно согласен, так будет лучше.

2. Я хотел показать как эту задачу можно решить с помощью функции АВТОНОМЕРЗАПИСИ() пронумеровав строки временной таблицы, конечно же, как справедливо было замечено, можно обойтись без нее, запрос в этом случае будет выглядеть следующим образом

Вариант запроса №2:

ВЫБРАТЬ РАЗЛИЧНЫЕ
СведенияОСотрудниках.Период КАК Период,
СведенияОСотрудниках.Сотрудник КАК Сотрудник,
СведенияОСотрудниках.Оклад КАК Оклад
ПОМЕСТИТЬ ВТ
ИЗ
РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
ГДЕ
СведенияОСотрудниках.Период МЕЖДУ &ПериодРегистрации И КОНЕЦПЕРИОДА(&ПериодРегистрации, МЕСЯЦ)

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

ВЫБРАТЬ
&ПериодРегистрации,
СведенияОСотрудникахСрезПоследних.Сотрудник,
СведенияОСотрудникахСрезПоследних.Оклад
ИЗ
РегистрСведений.СведенияОСотрудниках.СрезПоследних(&ПериодРегистрации, ) КАК СведенияОСотрудникахСрезПоследних

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

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
ВТНачало.Период КАК НачалоПериода,
МИНИМУМ(ДОБАВИТЬКДАТЕ(ЕСТЬNULL(ВТКонец.Период, ДОБАВИТЬКДАТЕ(&ПериодРегистрации, МЕСЯЦ, 1)), ДЕНЬ, -1)) КАК КонецПериода,
ВТНачало.Сотрудник КАК Сотрудник,
ВТНачало.Оклад КАК Оклад
ПОМЕСТИТЬ ВТ2
ИЗ
ВТ КАК ВТНачало
ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТКонец
ПО ВТНачало.Сотрудник = ВТКонец.Сотрудник
И ВТНачало.Период < ВТКонец.Период

СГРУППИРОВАТЬ ПО
ВТНачало.Период,
ВТНачало.Сотрудник,
ВТНачало.Оклад

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

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
НачислениеЗарплатыОсновныеНачисления.Сотрудник КАК Сотрудник,
ВЫБОР
КОГДА ВТ2.НачалоПериода < НачислениеЗарплатыОсновныеНачисления.ДатаНачала
ТОГДА НачислениеЗарплатыОсновныеНачисления.ДатаНачала
ИНАЧЕ ВТ2.НачалоПериода
КОНЕЦ КАК ДатаНачала,
ВЫБОР
КОГДА ВТ2.КонецПериода > НачислениеЗарплатыОсновныеНачисления.ДатаОкончания
ТОГДА НачислениеЗарплатыОсновныеНачисления.ДатаОкончания
ИНАЧЕ ВТ2.КонецПериода
КОНЕЦ КАК ДатаОкончания,
ВТ2.Оклад КАК Размер
ИЗ
ВТ2 КАК ВТ2
ПОЛНОЕ СОЕДИНЕНИЕ Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления
ПО ВТ2.Сотрудник = НачислениеЗарплатыОсновныеНачисления.Сотрудник
ГДЕ
НачислениеЗарплатыОсновныеНачисления.Ссылка = &Ссылка
И НачислениеЗарплатыОсновныеНачисления.ВидРасчета = &Оклад
И ВЫБОР
КОГДА ВТ2.НачалоПериода < НачислениеЗарплатыОсновныеНачисления.ДатаНачала
ТОГДА НачислениеЗарплатыОсновныеНачисления.ДатаНачала
ИНАЧЕ ВТ2.НачалоПериода
КОНЕЦ <= ВЫБОР
КОГДА ВТ2.КонецПериода > НачислениеЗарплатыОсновныеНачисления.ДатаОкончания
ТОГДА НачислениеЗарплатыОсновныеНачисления.ДатаОкончания
ИНАЧЕ ВТ2.КонецПериода
КОНЕЦ
Оставьте свое сообщение