Код: Выделить всё
TAB_DATE - день месяца
ADDIT_MARK-праздники/выходные (1-суббота, 3-воскр, 2 - праздник)
TIME_LENGTH_P-продолжительность смены
TODAY_STATE-состояние дня (0-выход на работу, >0 - невыходы на работу по различным причинам)
ID_CARD- карточка сотрудника
ID_CARD - карточка
DATE_START-дата нач. период
DATE_END-дата ок. периода
CATEGORY- категория сотрудника
Теперь вот такой запрос:
Необходимо вычислить дни, которые "Выходные и праздничные дни". Замечу, в один день может смена растянуться на два дня. то есть отработанные дни будут зацеплять и рабочий день и выходной. Например: выход в пятницу в 19-00,, продолжительностью 14 часов. Таким образом след день (суббота) не должен входить в список.
Теперь. Написана функция, которая высчитывает на сколько дней переходит смена.
Код: Выделить всё
CREATE PROCEDURE SP_GET_DAYS (
IN_DATE DATE,
IN_TIME TIME,
IN_LEN DECIMAL(15,2),
IN_GRAPHIC INTEGER)
RETURNS (
OUT_DAYS INTEGER)
AS
DECLARE VARIABLE D1 TIMESTAMP;
DECLARE VARIABLE D2 TIMESTAMP;
DECLARE VARIABLE DTIME0 TIME;
DECLARE VARIABLE LENTEMP DECIMAL(9,4);
begin
/*Процедура расчета отработанных дней с учетом переноса*/
IF (IN_TIME IS NULL OR IN_LEN=0) THEN
BEGIN
OUT_DAYS=0;
SUSPEND;
EXIT;
end
DTIME0 = '00:00:00';
D1 = CAST(IN_TIME AS TIMESTAMP);
D2 = CAST(IN_TIME AS TIMESTAMP);
D2 = D1+ IN_LEN/24.00;
--есть ли перенос на след. день?
if ( CAST(D1 as date) != CAST(D2 AS DATE) ) then
begin
--перенос есть
--првоерим, есть ли переход между месяцами?
if (EXTRACT(MONTH FROM IN_DATE) != EXTRACT(MONTH FROM IN_DATE+1) ) then
begin
--переход есть, и пока считаем, что будущий месяц не учитывается в этом.
OUT_DAYS = 1;
end
else
begin
OUT_DAYS = 2;
end
end
else
begin
--переноса нет между днями, все в пределах одного
OUT_DAYS = 1;
end
suspend;
end
Группировка идет по категориям. Сколько в каждой категории было выходных и праздников.
Код: Выделить всё
SELECT
VIEW_CONSOLIDATE.CATEGORY,
SUM( (
SELECT COUNT(TABEL.ID)
FROM TABEL TBL
WHERE
(TBL.ADDIT_MARK > 0) --ищем только субботы, воскр, празд
AND
(TBL.TIME_LENGTH_P = 0)--тогда, когда смены нет в день
AND
(TBL.TODAY_STATE not in( 8,9))--не учитываем отпуска
AND
(TABDATE BETWEEN VIEW_CONSOLIDATE.DATESTART AND VIEW_CONSOLIDATE.DATEEND)
AND
(TBL.ID_CARD = VIEW_CONSOLIDATE.ID_CARD)
AND
NOT EXISTS ( SELECT ID FROM TABEL T WHERE t.TABDATE = TBL.TABDATE AND T.ID_CARD = TBL.ID_CARD AND T.SMENA_LEN =1 )--не учитываем дни с переносами с прошлого месяца
AND
(SELECT OUT_DAYS FROM SP_GET_DAYS(TBL.TABDATE-1, (SELECT START_TIME_P FROM TABEL T1 WHERE T1.TABDATE = TBl.TABDATE-1 AND T1.ID_CARD = TBL.ID_CARD AND T1.SMENA_LEN=0) ,(SELECT T1.TIME_LENGTH_P FROM TABEL T1 WHERE T1.TABDATE = TBl.TABDATE-1 AND T1.ID_CARD = TBL.ID_CARD AND T1.SMENA_LEN=0),TBL.ID_GRAPHIC)) !=2
--учитываем дни, где смена не 2 дня
AND
TBL.TABDATE-1 >VIEW_CONSOLIDATE.DATESTART
)) CNT
FROM VIEW_CONSOLIDATE
WHERE
VIEW_CONSOLIDATE.DATESTART >='01.08.2007'
AND
VIEW_CONSOLIDATE.DATEEND <='31.08.2007'
AND
VIEW_CONSOLIDATE.ID_GROUP in (SELECT ID FROM SP_REC_GROUPS(0))
GROUP BY VIEW_CONSOLIDATE.CATEGORY
ORDER BY VIEW_CONSOLIDATE.CATEGORY
Запрос вызывает несколько вложенных запросов, а также обрабатывает вложенную процедуру. Насколько такой запрос корректен и реален для работы.
Сотрудников(периодов): 300.
Записей в табеле: 31*300=9300 на один месяц.