Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
Вот нашел в форуме такую штучку.
--Кол-во суббот и воскресений за период дат
declare @start smalldatetime, @end smalldatetime
select @start = '20070101', @end = '20070131'
select datediff (wk, @start - 7, @end - 6) + datediff (wk, @start - 8, @end - 7)

Вот думаю, можно ли формулой, вычислить конечную дату, если известна дата начала и требуемое кол-во рабочих дней :)
29 янв 07, 11:00    [3705936]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
RENaissance
Member

Откуда: Муром->Москва
Сообщений: 10895

DATEADD???


Posted via ActualForum NNTP Server 1.3

29 янв 07, 11:05    [3705963]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
RENaissance

DATEADD???

Пожалуйста продолжите свою мысль :)
29 янв 07, 11:10    [3705991]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
RENaissance
Member

Откуда: Муром->Москва
Сообщений: 10895

В BOL про DATEADD все расписано.


Posted via ActualForum NNTP Server 1.3

29 янв 07, 11:15    [3706020]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5637
количество рабочих дней есть.
количество суббот есть.
количество воскресений есть.

dateadd к началу даты количество дней.

для спящего время бодрствования равносильно сну
29 янв 07, 11:18    [3706036]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
RENaissance

В BOL про DATEADD все расписано.

--Заготовочка.
declare @start smalldatetime, @offset int
select @start = '20070111', @offset = 2
--Субботы и воскресения мы не считаем...
--Так что мне в DATEADD написать, что бы получить '20070115'?
29 янв 07, 11:23    [3706073]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
Алексей2003
количество рабочих дней есть.
количество суббот есть.
количество воскресений есть.


Я то же сначало так подумал :-) но это неправильно. посмотрите пример выше, у нас нет даты конечной что бы найти правильное кол-во выходных (суб/воскр.).
29 янв 07, 11:26    [3706092]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Maadox
Member

Откуда: anywhere
Сообщений: 106
Paul Chabinsky
Вот нашел в форуме такую штучку.
--Кол-во суббот и воскресений за период дат
declare @start smalldatetime, @end smalldatetime
select @start = '20070101', @end = '20070131'
select datediff (wk, @start - 7, @end - 6) + datediff (wk, @start - 8, @end - 7)

Вот думаю, можно ли формулой, вычислить конечную дату, если известна дата начала и требуемое кол-во рабочих дней :)


Если под раб. днями подразусеваются пн-пт, без учета празников, и надо отсчитать N рабочих дней, то к текущей дате надо добавить 7 * X(где Х = N/5 нацело).
Остается добавить только остаток от деления N/5, но он через case легко расписывается.
29 янв 07, 11:40    [3706196]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
Есть еще табличка с праздниками :)
И вот как бы это все вместе соединить... :)
29 янв 07, 11:48    [3706250]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Roman S. Golubin
Member

Откуда: 140002
Сообщений: 11541

Может сразу в табличку с праздниками и выходные добавить?


Posted via ActualForum NNTP Server 1.3

29 янв 07, 11:59    [3706339]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Maadox
Member

Откуда: anywhere
Сообщений: 106
Paul Chabinsky
Есть еще табличка с праздниками :)
И вот как бы это все вместе соединить... :)


Если дата, от которой отсчитываем, будний день, то работает вот это:
declare @Date smalldatetime,
        @N    int

select @Date = '20070125',
       @N    = 12

select datepart(wk, '20070125') -- Равно 4. Первый день недели понедельник.
select dateadd(dd, ((datepart(wk, @Date) + (@N % 5)) / 5) * 2  + (@N % 5), dateadd(dd, 7 *(@N/5), @Date ))

А праздники можно решить следующим алгоритмом.
1) Считаем как показано выше.
2) Считаем количество праздников попавших в интервал.
3) Если праздников нет - выход, иначе идем в п.1, добавляя количество праздников из п.2.
29 янв 07, 12:01    [3706360]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5503
Блог
"Уж сколько раз твердили миру" (С) Крылов (по-моему)
Заведите себе табличку со ВСЕМИ днями, лет на N (нет, N - мало, пусть будет М) вперед.
И там отмечайте, день рабочий или нет. Предварительно при заполнении - учесть субботы, воскресенья, гос. и прочие праздники. (Хотя можно взять другую любимую табличку - с последовательными числами, из нее DATEADD-ом сделать подзапрос с датами, к нему приджойнить табличку с праздниками - но тогда нужно еще проработать ситуацию, когда суббота или воскресенье рабочим днем становится. :) )

А далее - что-то типа:
DECLARE @daycnt int, @MaxWD datetime, @i int, @FromDate datetime
SELECT @fromDate = '20070101',
@i = 0
SELECT @i = @i + IsHoliday,
@MaxWD = CASE WHEN @i = @daycnt THEN workDate ELSE @MaxWD
FROM WorkDates
WHERE WorkDate<=DATEADD(dd, @daycnt*2 /*прозапас*/, @FromDate)
ORDER BY workDate
SELECT @MaxWD
Правда, недокументированно. :)

А в 2005-ом - вообще делаем подзапрос к табличке на выборку рабочих workDate с указанием TOP @daycnt, откуда выбираем максимальный.
29 янв 07, 12:09    [3706418]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
Да не нужны таблички, без них хочется. Мне нужна именно формула... к которой максимум вол-во выходных кустомных приходит еще.
29 янв 07, 12:17    [3706510]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
nergal
Member

Откуда: Екатеринбург
Сообщений: 1015
а можно занести только одну табличку со всеми праздниками
и считать сколько праздников выпало на период
а количество субот и воскресений, можно сосчитать встроенными функциями sql
29 янв 07, 12:19    [3706528]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Maadox
Member

Откуда: anywhere
Сообщений: 106
DeColo®es
"Уж сколько раз твердили миру" (С) Крылов (по-моему)
Заведите себе табличку со ВСЕМИ днями, лет на N (нет, N - мало, пусть будет М) вперед.


Есть способ более эффективный.
В таблице со всеми датами(или только рабочими) создать сквозную нумерацию рабочих дней.
Calendar, а ля.
Date............Num
20070125....5024
20070126....5025
20070129....5026
....
и два индекса, один по дате, другой по Num.
select Date
  from Calendar
 where Num = @N + (select Num
                     from Calendar
                    where Date = @Date 
                  )
Как поддерживать актуальность Num, в случае очередных указов президента, думаю не надо объяснять.


PS. А как воевать с хлопыванием пробелов в сообщении ?
29 янв 07, 12:20    [3706540]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5503
Блог
Paul Chabinsky
Да не нужны таблички, без них хочется. Мне нужна именно формула... к которой максимум вол-во выходных кустомных приходит еще.
А мне сервер вообще очень жить мешает. Гы.
Только без него программа не работает и зарплату не платють.

ЗЫ Кстати, я написал - как обойтись без таблиц со всеми днями.
29 янв 07, 12:24    [3706561]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5637
2Paul Chabinsky
просто так тоже может не получиться.
потому что в табличке может храниться суббота/воскресение, при этом праздник.

для спящего время бодрствования равносильно сну
29 янв 07, 12:35    [3706649]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Fffffffffffffff
Guest
Если это расчет стажа, то кадры считают так:
Отдельно год минус год, месяц-месяц, день-день.
Например: 27 февраля + 1 месяц = 27 марта.
29 янв 07, 12:40    [3706689]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Maadox
Member

Откуда: anywhere
Сообщений: 106
Paul Chabinsky
Да не нужны таблички, без них хочется. Мне нужна именно формула... к которой максимум вол-во выходных кустомных приходит еще.


День прищедший с календаря праздников увеличивает дату, и возможно, за счет этого увеличения, могут подхватиться еще праздники (31 дек + 1 день). Значит решение должно быть рекурсивным. Лучше иметь календарь рабочих дней, не так много занимает места, зато очень понятное и прозрачное решение.

PS. Самому приходится работать с прогой, в которой данная задача решена через таблицу, но без нумерации. Задача получения расчетных дат(добавления N раб. дней) решена через курсор по этой таблице и на больших N тормозит. Готов и сам исправить на свой вариант, да прав нет :(.
29 янв 07, 12:51    [3706785]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
Алексей2003
просто так тоже может не получиться.
потому что в табличке может храниться суббота/воскресение, при этом праздник.

Ну соботы и воскресения из таблички кустомных праздников исключить можно просто... :)
Например сделать представление, и отфильтровать...
CREATE VIEW CustomHolidays
AS
SELECT * FROM Holidays
WHERE datediff (wk, [date] - 8, [date] - 7) = 0 AND datediff (wk, [date] - 7, [date] - 6) = 0
29 янв 07, 12:52    [3706791]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5637
SET DATEFIRST 1
go
declare @d datetime, @i int
select @d = dateadd(dd, datediff(dd, 0, getdate()), 0), @i = 20
declare @t table(i int identity(1,1), d datetime)
insert into @t (d)

 select dateadd(dd, n1.number + n2.number*256 + 1, @d)
  from
   (select number from spt_values where type = 'p') n1
   cross join
    (select number from spt_values where type = 'p') n2
  where n1.number + n2.number*256 < @i+(floor(@i/365)+1)*100
   and datediff (wk, dateadd(dd, n1.number + n2.number*256 + 1, @d) - 8, dateadd(dd, n1.number + n2.number*256 + 1, @d) - 7) = 0 AND datediff (wk, dateadd(dd, n1.number + n2.number*256 + 1, @d) - 7, dateadd(dd, n1.number + n2.number*256 + 1, @d) - 6) = 0
 order by 1
select * from @t where i = @i
ну а дальше я думаю сами легко прикрутите свою вьюшку.

для спящего время бодрствования равносильно сну
29 янв 07, 13:14    [3706955]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Paul Chabinsky
Алексей2003
просто так тоже может не получиться.
потому что в табличке может храниться суббота/воскресение, при этом праздник.

Ну соботы и воскресения из таблички кустомных праздников исключить можно просто... :)
Например сделать представление, и отфильтровать...
CREATE VIEW CustomHolidays
AS
SELECT * FROM Holidays
WHERE datediff (wk, [date] - 8, [date] - 7) = 0 AND datediff (wk, [date] - 7, [date] - 6) = 0

Чего-то я не понял, 8,7,6 - это что такое?? Вы эти числа связываете с субботами и воскресеньями? Попробуйте выполнить вот такой скрипт:

SET DATEFIRST 1;
SELECT DATEPART(WEEKDAY, '20070128')[DATEFIRST 1];
SET DATEFIRST 2;
SELECT DATEPART(WEEKDAY, '20070128')[DATEFIRST 2];
SET DATEFIRST 3;
SELECT DATEPART(WEEKDAY, '20070128')[DATEFIRST 3];
SET DATEFIRST 4;
SELECT DATEPART(WEEKDAY, '20070128')[DATEFIRST 4];
SET DATEFIRST 5;
SELECT DATEPART(WEEKDAY, '20070128')[DATEFIRST 5];

Зависит от SET DATEFIRST, не так ли?
Инвариантом же является величина
(@@DATEFIRST+DATEPART(WEEKDAY,[date])%7
, которая для субботы равна 0, а для воскресенья - 1.
Кроме того, какой смысл, по-Вашему, несёт функция DATEDIFF(WEEK, [date1], [date2])? На самом деле функция возвращает количество переходов от субботы к воскресенью между аргументами, независимо от @@DATEFIRST. Все эти факты неоднократно обсуждались на форуме.
Так что, Вам надо ещё подумать...
29 янв 07, 13:15    [3706969]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
iap
Инвариантом же является величина
(@@DATEFIRST+DATEPART(WEEKDAY,[date])%7
, которая для субботы равна 0, а для воскресенья - 1.

Скобку пропустил:
(@@DATEFIRST+DATEPART(WEEKDAY,[date]))%7
29 янв 07, 13:18    [3707005]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Maadox
Member

Откуда: anywhere
Сообщений: 106
iap

...Зависит от SET DATEFIRST, не так ли?
Инвариантом же является величина
(@@DATEFIRST+DATEPART(WEEKDAY,[date])%7


А можно и по-другому.
-- 1 понедельник..7 воскресенье
SET DATEFIRST 3
select (datepart(WEEKDAY, getdate())-datepart(WEEKDAY, 0)+7)%7 + 1
SET DATEFIRST 5
select (datepart(WEEKDAY, getdate())-datepart(WEEKDAY, 0)+7)%7 + 1
29 янв 07, 13:33    [3707143]     Ответить | Цитировать Сообщить модератору
 Re: Выходные/Рабочие  [new]
Paul Chabinsky
Member

Откуда:
Сообщений: 322
2iap

declare @date smalldatetime
set @date = '20070101'
set datefirst 1 select datediff (wk, @date - 2, @date - 1) --понедельник
set datefirst 2 select datediff (wk, @date - 2, @date - 1) --понедельник
set datefirst 3 select datediff (wk, @date - 2, @date - 1) --понедельник
set datefirst 4 select datediff (wk, @date - 2, @date - 1) --понедельник
set datefirst 5 select datediff (wk, @date - 2, @date - 1) --понедельник
set datefirst 6 select datediff (wk, @date - 2, @date - 1) --понедельник
set datefirst 7 select datediff (wk, @date - 2, @date - 1) --понедельник
29 янв 07, 13:35    [3707172]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить