Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Firebird, Interbase > Расчет количества выходных


Автор: aleks88 1.2.2012, 05:01
Здравствуйте! Подскажите как расчитать либо количество рабочих дней, либо количеств выходных между двумя датами?
В итоге должен быть вычисляемый стобец, использующий в котором прибавляется к дате количество дней.


Автор: Deniz 1.2.2012, 05:35
aleks88, а причем тут FireBird?
Если в хранимой процедуре, то нужно указать версию сервера, от этого многое зависит.
Можно использовать http://www.firebirdsql.su/doku.php?id=extract.

Автор: aleks88 1.2.2012, 06:18
Версия сервера 2.1.4
Подскажите, как сделать следующее:
Есть поле с датой (Date), есть поле с количеством дней(Integer), есть некое бинарное поле [0,1] и есть расчитываемое поле.
Если банарное поле равно 0, то расчитываемое поле = поле с датой + количество дней.
Если бин. поле = 1, то расчитываемое поле = поле с датой + количество дней + количество выходных, выпадаемых за эти дни.

Совсем не представляю как это сделат.
Есть идея создавать файл Exel, там есть функция расчета числа рабочих дней между датами. Ииходя из этого, расчитывать все в Exe и читать программно в базу данных. Но веть это извращенство smile

Автор: AndreyIQ 1.2.2012, 07:18
Первое, что приходит в голову (без дополнительных модулей) добавить таблицу с выходными.

Автор: aleks88 1.2.2012, 07:34
Мне тоже это приходило, но корректно ли будет вычисляться дата, если скажем, найдет количеств выходных, прибавим к начальной дате и где то опять попадет на выходные ?

На сколько рационално испльзовать Exel ? Там есть встроенная функция, сдвигающая дату на определенное количество рабочих дней.
Т.е. выгрузили в файл Ексела дату и число дней, считали результат и записали в таблицу.

Автор: AndreyIQ 1.2.2012, 07:58
Тогда лучше написать хранимую процедуру.
ЗЫ Про Excel забудьте
ЗЗЫ Возможно есть UDF'ки для вашей задачи

Автор: aleks88 1.2.2012, 08:50
Сложность в том, что с хранимыми процедурами не работал. :(
UDF это что ?
Почему про эксел забыть? В чем проблемы ?

Автор: aleks88 1.2.2012, 09:31
Подумал тут над хранимой процедурой. Неформальным языком должнобыть так:
1. Передать начальную дату и количество рабочих дней
2. Увеличиваем в цикле дату на 1 день и проверяем, выходной это или нет
3. если нет, то уменьшем количество рабочих дней на 1
4. как только количество рабочих дней станет равное нулю, выходим из цикла и возвращаем дату.

Я на верном пути ?

Автор: AndreyIQ 1.2.2012, 10:55
Через Excel делать это извращение, дикие тормоза и т.д.

Насчет, хранимой процедуры, Вы на верном пути.

Автор: Deniz 1.2.2012, 11:00
Цитата(aleks88 @  1.2.2012,  11:31 Найти цитируемый пост)
Я на верном пути?
Да.
Осталось только определить что есть выходной день? Суббота и воскресенье? Или добавить праздники?
Для праздников нужна отдельная таблица.
PS: UDF и Excel использовать не надо, достаточно хранимой процедуры.

Автор: Frees 1.2.2012, 11:31
Цитата(Deniz @  1.2.2012,  14:00 Найти цитируемый пост)
использовать не надо, достаточно хранимой процедуры.

Код

CREATE OR ALTER PROCEDURE GET_WEEKEND_COUNT (
    DATE_FROM DATE,
    DATE_TO DATE)
RETURNS (
    WEEKEND_COUNT INTEGER)
AS
BEGIN
  WEEKEND_COUNT = 0;
  WHILE (DATE_FROM < DATE_TO) DO
  BEGIN
    DATE_FROM = DATE_FROM + 1;
    IF (EXTRACT(WEEKDAY FROM :DATE_FROM) IN (0, 6)) THEN --0,6 - ВРОДЕ выходные
      WEEKEND_COUNT = WEEKEND_COUNT + 1;
  END
  SUSPEND;
  --Доработать напильником
END

Автор: aleks88 1.2.2012, 11:46
Эх, тяжко с налету что то делать ...
Благодарю всех за содействие! Буду разбираться в процедуре! smile

Автор: Deniz 1.2.2012, 12:22
Frees, там задача немного поменялась.
Очень похожа на задачу определения дня выхода на работу из отпуска.
PS: процедуру писать не буду, пусть автор сам немного поразмыслит, тем более пример уже дан.

Автор: Akella 1.2.2012, 14:45
Цитата(aleks88 @  1.2.2012,  05:01 Найти цитируемый пост)
вычисляемый стобец, использующий в котором прибавляется к дате количество дней.

сам хоть понял, что написал?

Автор: aleks88 1.2.2012, 18:09
Цитата(Akella @ 1.2.2012,  14:45)
Цитата(aleks88 @  1.2.2012,  05:01 Найти цитируемый пост)
вычисляемый стобец, использующий в котором прибавляется к дате количество дней.

сам хоть понял, что написал?

Виноват, казус smile

Цитата(Deniz @ 1.2.2012,  12:22)
Frees, там задача немного поменялась.
Очень похожа на задачу определения дня выхода на работу из отпуска.
PS: процедуру писать не буду, пусть автор сам немного поразмыслит, тем более пример уже дан.

Да, заметил что задача немногим отличается, но не существенно...
Вот, плод моих скудных размышлений, все верно ? На мой взгляд да, дата сдвигается на число рабочих дней (под рабочими понимаем все кроме СБ и ВС).

Одно пока не ясно, как завязать на процедуру вычисляемый столбец , т.е. как при добавлении строки, передать в процедуру параметры из этой строки и занести возвращаемое значение в столбец :( 


Код

CREATE PROCEDURE DATE_COLCULATION (DATE_FROM DATE, DAYS INTEGER)
RETURNS ( DATE_TO DATE )
AS
BEGIN
  WHILE(DAYS > 0) DO
  BEGIN
    DATE_FROM = DATE_FROM + 1;
    IF (EXTRACT(WEEKDAY FROM :DATE_FROM) IN (1,2,3,4,5)) 
    THEN DAYS=DAYS-1;
  END
DATE_TO=DATE_FROM;
  SUSPEND;
END  

    

Автор: aleks88 2.2.2012, 04:02
Немного подумав пришел к выводу:
Возможно ли использовать триггер и вызывать из него ХП.
Тригер запускается на добавление строки, в процедуру передаются 2 параметра и возвращается 1, который записывается с толбец ?
Кокой синтаксис для присвоения значения, возвращаемого ХП переменно ?

Автор: Deniz 2.2.2012, 05:52
Цитата(aleks88 @  1.2.2012,  20:09 Найти цитируемый пост)
Вот, плод моих скудных размышлений, все верно ? На мой взгляд да
На мой взгляд не совсем.
Для примера передай в процедуру:
1. 03.02.2012, 2
2. 04.02.2012, 2
Сравни результаты, это правильные результаты?
Цитата(aleks88 @  2.2.2012,  06:02 Найти цитируемый пост)
Возможно ли использовать триггер и вызывать из него ХП.
возможно.

Цитата(aleks88 @  2.2.2012,  06:02 Найти цитируемый пост)
Кокой синтаксис для присвоения значения, возвращаемого ХП переменно ? 
примерно так
Код
select date_to from DATE_COLCULATION (new.DATE_FROM, new.DAYS ) into new.date_to;

Автор: aleks88 2.2.2012, 06:16
Да, результаты верны, но это все равно мелочи smile

Нужно реализовать следующую логику:

Есть поля:
   Date1, Date2, Date3
   Int1

Поля Date3 заполняется следующим образом:
  Если Date2 не пусто, то Date3=Date2
  Если Date2 пусто, то Date3="результат, возвращенный процедурой, которая получает на вход Date1 и Int1"

Т.е. нужно получить автозаполняемое поле, которое изменяется при создании строки или изменении.
ЗЫ. Извиняюсь за язык описания smile

Я предполагаю решение: создать тригер на действия INSERT и UPDATE  и вызывать ХП в нем. Но конкретно написать не получается.
Можно пример как можно более приближенный к данной задачи ? smile  

Автор: aleks88 2.2.2012, 07:24
Разобрался с горем пополам. Позже выложу, на проверку качества smile

Автор: Deniz 2.2.2012, 08:33
Цитата(aleks88 @  2.2.2012,  08:16 Найти цитируемый пост)
Да, результаты верны, но это все равно мелочи smile
Видать в MS так же думали.
Вот как Excel считает:
Код
Дата начала  Дни   Дата расчета
01.02.2012    2    03.02.2012
02.02.2012    2    06.02.2012
03.02.2012    2    07.02.2012
04.02.2012    2    07.02.2012
05.02.2012    2    07.02.2012
06.02.2012    2    08.02.2012
Считаем по календарю:
Для 01.02.2012 считаем раб дни (2 шт.): это 01 и 02 след раб день это 03
Для 02.02.2012 считаем раб дни (2 шт.): это 02 и 03 след раб день это 06
Для 03.02.2012 считаем раб дни (2 шт.): это 03 и 06 след раб день это 07
Для 04.02.2012 считаем раб дни (2 шт.): это 06 и 07 след раб день это 08
Для 05.02.2012 считаем раб дни (2 шт.): это 06 и 07 след раб день это 08
Для 06.02.2012 считаем раб дни (2 шт.): это 06 и 07 след раб день это 08
ИМХО, неправильный расчет, т.е. в диапазоне дат учитывается только конечная дата, начальная не учитывается.
PS: хотя для каких целей использовать.

Автор: tishaishii 3.3.2012, 20:20
С установкой Firebird прилагаются UDF.
Для регистрации функции выполни код:
Код
DECLARE EXTERNAL FUNCTION ADDDAY2
    TIMESTAMP,
    INTEGER,
    TIMESTAMP
RETURNS PARAMETER 3
ENTRY_POINT 'addDay2' MODULE_NAME 'fbudf';


Вариант применения:
Код
select addday2('2012-02-28', -2) from rdb$database

Автор: tishaishii 3.3.2012, 22:14
Код
select
     ws1."DATE"
from
     work_shedule as ws1
where
     (ws1."DATE" between ?in_date_from and ?in_date_to) and
     (ws1.dayoff<>0)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)