Имя: Пароль:
1C
 
Помогите с запросом, срез последних на каждый день + дополнение из регистра
0 breezee
 
04.09.17
20:36
Добрый день! Готовлюсь к спецу по платформе, есть документ "РасчетЗП" и регистр "Сведения о сотрудниках". Мне надо получить данные по сотруднику и подразделению из регистра "Сведения о сотрудниках". Я получаю данные по окладу на даты в документе "РасчетЗП" и Даты изменения из регистра с окладами. А что дальше делать с данными не понимаю. Подскажите, пожалуйста, как полученными мной "интервалами" разбить периоды. То есть получается таблица вида:
Бельдыев    Бухгалтерия    04.09.2017    08.09.2017    30.09.2017    Да    100,00
Бельдыев    Бухгалтерия    15.09.2017    Не важно что за дата    Не важно что за дата    Нет    20,00
Бельдыев    Бухгалтерия    17.09.2017    Не важно что за дата    Не важно что за дата    Нет    14,00

А мне нужна:
Бельдыев    Бухгалтерия    08.09.2017    30.09.2017    Да    100,00
Бельдыев    Бухгалтерия    15.09.2017    17.09.2017    Нет    20,00
Бельдыев    Бухгалтерия    17.09.2017    30.09.2017    Нет    14,00

Как это сделать?

Текущий запрос:
ВЫБРАТЬ
    НачислениеЗарплатыОсновныеНачисления.Сотрудник КАК Сотрудник,
    НачислениеЗарплатыОсновныеНачисления.Подразделение КАК Подразделение,
    НачислениеЗарплатыОсновныеНачисления.ДатаНачала КАК ДатаНачала,
    НачислениеЗарплатыОсновныеНачисления.ДатаОкончания КАК ДатаОкончания
ПОМЕСТИТЬ ВТ_Документа
ИЗ
    Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления
ГДЕ
    НачислениеЗарплатыОсновныеНачисления.Ссылка = &Ссылка

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

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

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

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

ВЫБРАТЬ
    ВТ_Документа.Сотрудник,
    ВТ_Документа.Подразделение,
    ВТ_Документа.ДатаНачала,
    ВТ_Документа.ДатаОкончания,
    СведенияОСотрудниках.Период,
    ЛОЖЬ
ИЗ
    ВТ_Документа КАК ВТ_Документа
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
        ПО ВТ_Документа.Сотрудник = СведенияОСотрудниках.Сотрудник
            И ВТ_Документа.Подразделение = СведенияОСотрудниках.Подразделение
            И (СведенияОСотрудниках.Период МЕЖДУ ВТ_Документа.ДатаНачала И ВТ_Документа.ДатаОкончания)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Данных.Сотрудник КАК Сотрудник,
    ВТ_Данных.Подразделение КАК Подразделение,
    ВТ_Данных.Период КАК Период,
    ВЫБОР
        КОГДА ВТ_Данных.ЭтоСрезНаДаты
            ТОГДА ВТ_Данных.ДатаНачала
        ИНАЧЕ "Не важно что за дата"
    КОНЕЦ КАК ДатаНачала,
    ВЫБОР
        КОГДА ВТ_Данных.ЭтоСрезНаДаты
            ТОГДА ВТ_Данных.ДатаОкончания
        ИНАЧЕ "Не важно что за дата"
    КОНЕЦ КАК ДатаОкончания,
    ВТ_Данных.ЭтоСрезНаДаты КАК ЭтоСрезНаДаты,
    СведенияОСотрудниках.Оклад КАК Оклад
ИЗ
    ВТ_Данных КАК ВТ_Данных
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
        ПО ВТ_Данных.Сотрудник = СведенияОСотрудниках.Сотрудник
            И ВТ_Данных.Подразделение = СведенияОСотрудниках.Подразделение
            И ВТ_Данных.Период = СведенияОСотрудниках.Период

УПОРЯДОЧИТЬ ПО
    ДатаНачала
1 breezee
 
04.09.17
20:38
(0) Извините, нужна таблица вида:
Бельдыев    Бухгалтерия    08.09.2017    15.09.2017       100,00
Бельдыев    Бухгалтерия    15.09.2017    17.09.2017    20,00
Бельдыев    Бухгалтерия    17.09.2017    30.09.2017    14,00
2 Хрыч
 
04.09.17
20:49
Зачем тебе документ, если в РС вся необходимая информация есть?
3 breezee
 
04.09.17
20:52
(2) Нет там необходимой информации. В регистре хранится только сведений об окладе. Сведения о выходе/невыходе в документе. То есть инфа о том что сотрудник работал с 04.09 по 08.09 хранится только в ТЧ Документа
4 breezee
 
04.09.17
20:57
На случай если я плохо описал задачу, вот из билета:
Сотрудники предприятия получают оплату по окладу пропорционально отработанному времени в часах. Часовая ставка рассчитывается как начальное значение оклада, деленное на количество рабочих часов в том же периоде, что и фактически отработанные часы. В течение расчетного периода первоначальное значение оклада может быть неоднократно изменено. В информационной базе необходимо хранить историю его изменения. Расчет должен проводиться исходя из действующего на рассчитываемую дату начального значения оклада. Например, если начальное значение оклада изменилось 10 августа, то до 10 августа при расчете берется старое значение, а начиная с 10 августа – новое.

Помогите, плз, весь день над ней бьюсь
5 Хрыч
 
04.09.17
21:01
то бишь в ТЧ документа есть список работников с периодами их фактической работы, а в РС оклад, и надо начислить зарплату?
6 breezee
 
04.09.17
21:03
(5) Да, все верно
7 Хрыч
 
04.09.17
21:08
Здесь сразу нужно допустить, что по одному работнику может быть несколько строк с непересекающимися интервалами. Например, Петров с 01.08 по 10.08 и с 11.08 по 30.08. просто потому, что это учебная задача, и экзаменатор от тебя извращений не ждет.
8 breezee
 
04.09.17
21:12
(7) Спасибо, интервалы действительно не пересекаются, но вот оклад может изменяться хот тыщу раз и эти строки нужны в результате. И как это в запросе разбить я ума не приложу(
9 breezee
 
04.09.17
21:13
(7) Если есть идеи - подскажите, пожалуйста, можно на словах, не кодом
10 Хрыч
 
04.09.17
21:14
Я имею в виду, что дата изменения оклада никогда не попадает в середину интервала. То есть строки документа дробить не надо.
11 Хрыч
 
04.09.17
21:15
А дальше читаешь строки документа, связываешь с регистром по сотруднику и подразделению и для начала каждого периода выбираешь последнюю дату изменения.
12 Хрыч
 
04.09.17
21:16
То есть максимум даты, предшествующей началу интервала
13 Хрыч
 
04.09.17
21:17
По этим трем ключевым признакам: подразделение, сотрудник, дата изменения - получаешь соответствующую запись регистра с окладом
14 breezee
 
04.09.17
21:17
(11) Срез последних на дату? Это я сделал)
(10) А потом мне балл за упрощению снимут :D И так 1 раз не сдал уже(по другой причине)
15 Хрыч
 
04.09.17
21:23
Нет, срез последних не получится, потому что у тебя список сотрудников, и у каждого свой интервал. Надо брать основную таблицу регистра и связываеть его со строками документа по подразделению (равно), сотруднику (равно) и дате (не больше), группировать по подразделению и сотруднику с функцией максимум для периода. Так получишь временную таблицу с последними изменениями для каждого подразделение+сотрудник+интервал
16 Хрыч
 
04.09.17
21:26
(14) нет, такую упрощенку допускает сам Белоусов на консультации. Просто тупо пишет две строки, исходя из того, что изменился оклад
17 Хрыч
 
04.09.17
21:29
Эту временную таблицу опять связываешь с регистром (только теперь все равно) и получаешь соответвующую запись с окладом для каждого  Подразделение+Сотрудник+Интервал
18 Хрыч
 
04.09.17
21:31
(15) группировать по подразделению, сотруднику и интервалу конечно
19 Хрыч
 
04.09.17
22:24
+Code
Процедура ОбработкаПроведения(Отказ, Режим)
    
    // регистр ОсновныеНачисления
    Движения.ОсновныеНачисления.Записывать = Истина;
    Для Каждого ТекСтрокаОсновныеНачисления Из ОсновныеНачисления Цикл
        Движение = Движения.ОсновныеНачисления.Добавить();
        Движение.Сторно = Ложь;
        Движение.ВидРасчета = ТекСтрокаОсновныеНачисления.ВидРасчета;
        Движение.ПериодДействияНачало = ТекСтрокаОсновныеНачисления.ДатаНачала;
        Движение.ПериодДействияКонец = КонецДня(ТекСтрокаОсновныеНачисления.ДатаОкончания);
        Движение.ПериодРегистрации = Дата;
        Движение.Сотрудник = ТекСтрокаОсновныеНачисления.Сотрудник;
        Движение.Подразделение = ТекСтрокаОсновныеНачисления.Подразделение;
    КонецЦикла;
    
    Движения.Записать();
    
    //РАСЧЕТ ПО ОКЛАДУ
    
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    ОсновныеНачисленияДанныеГрафика.НомерСтроки,
        |    ОсновныеНачисленияДанныеГрафика.Сотрудник КАК Сотрудник,
        |    ОсновныеНачисленияДанныеГрафика.Подразделение КАК Подразделение,
        |    ОсновныеНачисленияДанныеГрафика.ПериодДействияНачало,
        |    ОсновныеНачисленияДанныеГрафика.ПериодДействияКонец,
        |    ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.ЗначениеПериодДействия, 0) КАК Норма,
        |    ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия КАК Факт
        |ПОМЕСТИТЬ вт_ДанныеГрафика
        |ИЗ
        |    РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(
        |            Регистратор = &Регистратор
        |                И ВидРасчета = &Оклад) КАК ОсновныеНачисленияДанныеГрафика
        |
        |ИНДЕКСИРОВАТЬ ПО
        |    Сотрудник,
        |    Подразделение
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ДанныеГрафика.Сотрудник КАК Сотрудник,
        |    ДанныеГрафика.Подразделение КАК Подразделение,
        |    ДанныеГрафика.ПериодДействияНачало,
        |    МАКСИМУМ(СведенияОСотрудниках.Период) КАК Период
        |ПОМЕСТИТЬ вт_ДатыОкладов
        |ИЗ
        |    вт_ДанныеГрафика КАК ДанныеГрафика
        |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
        |        ПО ДанныеГрафика.Сотрудник = СведенияОСотрудниках.Сотрудник
        |            И ДанныеГрафика.Подразделение = СведенияОСотрудниках.Подразделение
        |            И ДанныеГрафика.ПериодДействияНачало >= СведенияОСотрудниках.Период
        |
        |СГРУППИРОВАТЬ ПО
        |    ДанныеГрафика.Сотрудник,
        |    ДанныеГрафика.Подразделение,
        |    ДанныеГрафика.ПериодДействияНачало
        |
        |ИНДЕКСИРОВАТЬ ПО
        |    Сотрудник,
        |    Подразделение,
        |    Период
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ДатыОкладов.Сотрудник КАК Сотрудник,
        |    ДатыОкладов.Подразделение КАК Подразделение,
        |    ДатыОкладов.ПериодДействияНачало КАК ПериодДействияНачало,
        |    СведенияОСотрудниках.Оклад
        |ПОМЕСТИТЬ вт_Оклады
        |ИЗ
        |    вт_ДатыОкладов КАК ДатыОкладов
        |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
        |        ПО ДатыОкладов.Сотрудник = СведенияОСотрудниках.Сотрудник
        |            И ДатыОкладов.Подразделение = СведенияОСотрудниках.Подразделение
        |            И ДатыОкладов.Период = СведенияОСотрудниках.Период
        |
        |ИНДЕКСИРОВАТЬ ПО
        |    Сотрудник,
        |    Подразделение,
        |    ПериодДействияНачало
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ДанныеГрафика.НомерСтроки,
        |    ДанныеГрафика.Сотрудник,
        |    ДанныеГрафика.Подразделение,
        |    ДанныеГрафика.ПериодДействияНачало,
        |    ДанныеГрафика.ПериодДействияКонец,
        |    ДанныеГрафика.Норма,
        |    ДанныеГрафика.Факт,
        |    Оклады.Оклад
        |ИЗ
        |    вт_ДанныеГрафика КАК ДанныеГрафика
        |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ вт_Оклады КАК Оклады
        |        ПО ДанныеГрафика.Сотрудник = Оклады.Сотрудник
        |            И ДанныеГрафика.Подразделение = Оклады.Подразделение
        |            И ДанныеГрафика.ПериодДействияНачало = Оклады.ПериодДействияНачало";
    
    
    Запрос.УстановитьПараметр("Регистратор", Ссылка);
    Запрос.УстановитьПараметр("Оклад", ПланыВидовРасчета.ОсновныеНачисления.Оклад);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаДляОклада = РезультатЗапроса.Выбрать();
    
    Для каждого СтрокаНабора Из Движения.ОсновныеНачисления Цикл
        ВыборкаДляОклада.Сбросить();
        ВыборкаДляОклада.НайтиСледующий(СтрокаНабора.НомерСтроки, "НомерСтроки");
    
        СтрокаНабора.Результат = ?(ВыборкаДляОклада.Норма = 0, 0,
            ВыборкаДляОклада.Оклад / ВыборкаДляОклада.Норма * ВыборкаДляОклада.Факт);
            
        СтрокаНабора.Размер = ВыборкаДляОклада.Оклад;    
        СтрокаНабора.Отработано = ВыборкаДляОклада.Факт;
    КонецЦикла;
    Движения.ОсновныеНачисления.Записать(, Истина);
    
КонецПроцедуры
-Code
20 breezee
 
05.09.17
04:44
(19) (16)
Понял, спасибо!
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.