Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Здравствуйте!
У меня есть таблица, содержащая записи о приеме и увольнении сотрудников:
дата | id_Сотрудника | Должность | id_Магазина | Принят или уволен
Вопрос: как посчитать сколько человек трудоустроено в магазине на должностях в определенный день? Я имею в виду: 10.11.2012 в магазине А трудоустроено: 10 продавцов, 2 администратора, 4 кассира.
Прикрепляю таблицу. Буду благодарен любому совету. Спасибо.
Выкладываю пример:
Table1:
LOAD * INLINE [
Date, IdPerson, Flag
01.02.2014, A, 1
01.04.2014, B, 1
11.05.2014, C, 1
30.04.2014, A, -1
30.04.2014, B, -1
31.05.2014, C, -1
];
//Определяем диапазон
tmp1:
LOAD min(Date) as 'DateStart', max(Date) as 'DateEnd' Resident Table1;
LET Date_Start = peek('DateStart',0,'tmp1');
LET Date_End = peek('DateEnd',0,'tmp1');
DROP Table tmp1;
LET NumOfDays = Date_End - Date_Start + 1;
//Формируем календарь
Date_src:
LOAD
$(Date_Start) + Rowno() -1 as DateId
AUTOGENERATE $(NumOfDays);
Calendar:
LOAD
DateId,
year(DateId) as 'год',
dual('Кв.' & ceil(month(DateId)/3),ceil(month(DateId)/3)) as 'квартал',
dual('Кв.' & ceil(month(DateId)/3) & '-' & year(DateId),year(DateId) & ceil(month(DateId)/3)) as 'квартал-год',
month(DateId) as 'месяц',
ceil(month(DateId)) as 'месяц номер',
dual(month(DateId) & '-' & year(DateId),year(DateId) & num(month(DateId), '00')) as 'месяц-год',
week(DateId) as 'неделя',
weekday(DateId) as 'день недели',
date(DateId) as 'Дата',
day(DateId) as 'день'
RESIDENT Date_src;
Drop Table Date_src;
//Готовим сведения для подсчета по интервалам
table2:
load
Date as [ДатаПринят],
IdPerson
Resident Table1
Where Flag=1;
join load
Date as [ДатаУволен],
IdPerson
Resident Table1
Where Flag=-1;
DROP Table Table1;
//Формируем сведения по наличию персонала на каждый календарный день
count_tmp:
IntervalMatch (Дата) LOAD [ДатаПринят], [ДатаУволен] RESIDENT table2;
В Вашем случае потребуется избавится от пустых записей по должностям.
Проверить корректность данных (встречаются записи о приеме в одном магазине, а об увольнении в другом, пересечение периодов работы по сотруднику в разных магазинах,...)
Дата приема на работу должна быть по всем позициям. как и дата увольнения. У тех кто работает - ставим текущую дату в качестве даты увольнения.
День добрый.
Суббота, под рукой примера нет
Первое, что я бы сделал - избавился бы от признака (принят/уволен) и сформировал бы две колонки, дата приема и дата увольнения.
Затем (для простого случая без подсчета по категориям)
count_tmp:
IntervalMatch (дата(все даты календаря)) LOAD [Дата приема], [Дата увольнения] RESIDENT [таблица с датами];
Далее идет подсчет
LOAD дата ,
Count(дата) as 'РаботниковВДень',
Resident count_tmp
group by дата;
Получаем количество на каждый день календаря.
P.S. Вот такая идея, надеюсь поможет. Инструмент не под рукой
Выкладываю пример:
Table1:
LOAD * INLINE [
Date, IdPerson, Flag
01.02.2014, A, 1
01.04.2014, B, 1
11.05.2014, C, 1
30.04.2014, A, -1
30.04.2014, B, -1
31.05.2014, C, -1
];
//Определяем диапазон
tmp1:
LOAD min(Date) as 'DateStart', max(Date) as 'DateEnd' Resident Table1;
LET Date_Start = peek('DateStart',0,'tmp1');
LET Date_End = peek('DateEnd',0,'tmp1');
DROP Table tmp1;
LET NumOfDays = Date_End - Date_Start + 1;
//Формируем календарь
Date_src:
LOAD
$(Date_Start) + Rowno() -1 as DateId
AUTOGENERATE $(NumOfDays);
Calendar:
LOAD
DateId,
year(DateId) as 'год',
dual('Кв.' & ceil(month(DateId)/3),ceil(month(DateId)/3)) as 'квартал',
dual('Кв.' & ceil(month(DateId)/3) & '-' & year(DateId),year(DateId) & ceil(month(DateId)/3)) as 'квартал-год',
month(DateId) as 'месяц',
ceil(month(DateId)) as 'месяц номер',
dual(month(DateId) & '-' & year(DateId),year(DateId) & num(month(DateId), '00')) as 'месяц-год',
week(DateId) as 'неделя',
weekday(DateId) as 'день недели',
date(DateId) as 'Дата',
day(DateId) as 'день'
RESIDENT Date_src;
Drop Table Date_src;
//Готовим сведения для подсчета по интервалам
table2:
load
Date as [ДатаПринят],
IdPerson
Resident Table1
Where Flag=1;
join load
Date as [ДатаУволен],
IdPerson
Resident Table1
Where Flag=-1;
DROP Table Table1;
//Формируем сведения по наличию персонала на каждый календарный день
count_tmp:
IntervalMatch (Дата) LOAD [ДатаПринят], [ДатаУволен] RESIDENT table2;
В Вашем случае потребуется избавится от пустых записей по должностям.
Проверить корректность данных (встречаются записи о приеме в одном магазине, а об увольнении в другом, пересечение периодов работы по сотруднику в разных магазинах,...)
Дата приема на работу должна быть по всем позициям. как и дата увольнения. У тех кто работает - ставим текущую дату в качестве даты увольнения.
Большое спасибо, Евгений! Похоже, ваш метод подходит. Вы правы, первостепенная задача разобраться с исходными данными, они берутся из регистра сведений 1С, в котором содержатся записи не только о приеме и увольнении, но и о командировках, изменениях разрядов и т.п. Я решил упростить себе задачу и взял только записи о приеме и увольнении, но оказалось не все так просто... Разберусь с этим за выходные и обязательно отпишусь.
После приведения регистра сведений к таблице вида: Сотрудник - ДатаПриема - ДатаУвольнения; всё решение свелось к джойну IntervalMatch'а к этой самой таблице. Получаем на каждый день календаря записи сотрудников, трудоустроенных в этот день. Далее удобно воспользоваться сводной таблицей с измерениями Дата, Магазин, Должность и подсчетом id сотрудников.
Евгений, еще раз спасибо!
Сотрудники:
LOAD id_Сотрудника,
ФИО,
Должность,
id_Организации,
AutoNumber(id_Склада, 'Склады') as id_Склада,
ДатаПриема,
if(isNull(ДатаУвольнения),Date(Date#(today(), 'DD.MM.YYYY'), 'DD.MM.YYYY'),ДатаУвольнения) as ДатаУвольнения,
ИзмДолжности,
Перевод,
Key
FROM
КадровыеПриказы.qvd
(qvd);
left join (Сотрудники)
IntervalMatch (Дата)
LOAD
ДатаПриема,
ДатаУвольнения
RESIDENT Сотрудники
;