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

Откуда:
Сообщений: 107
Доброго времени суток.
Поиском не нашел, так что не серчайте =).

Необходимо скопировать данные прошлого месяца на новый, по полю datetime, при этом необходимо учесть только рабочие дни, соответственно 2-е марта 2011 надо копировать не на 2-е апреля а на 4-е т.к. суббота не рабочая. Может кто сталкивался с такой задачей?
13 апр 11, 12:20    [10511440]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
Jovanny
Member

Откуда:
Сообщений: 1196
Может, что-то типа этого?

CREATE TABLE [dbo].[Table_1](
	[Id] [int] NOT NULL,
	[Date] [datetime] NOT NULL,
	[Hours] [real] NOT NULL
) ON [PRIMARY]

INSERT INTO Table_1 (Id,[Date],[Hours])
SELECT Id, 
	CASE WHEN [Date] BETWEEN '2011-03-02' AND '2011-03-03' THEN DATEADD(DAY, 33, [Date])
				ELSE DATEADD(MONTH, 1, [Date]) END,
	[Hours] FROM Table_1 WHERE [Date] BETWEEN '2011-03-01' AND '2011-04-01'
13 апр 11, 12:47    [10511649]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
syavik
Member

Откуда:
Сообщений: 107
Jovanny,

Спасибо, это будет работать правильно, но только в данном случае. Я хочу создать процедуру, которая бы в начале каждого месяца копировала определенные данные на новый месяц, и очень бы хотелось автоматизировать процесс...
13 апр 11, 12:53    [10511697]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
iljy
Member

Откуда:
Сообщений: 8711
syavik,

а как вы планируете решать ситуацию, когда в следующем месяце рабочих дней меньше. Вообще задача довольно тривиальная: сгенерите таблицу дат, в ней для каждой даты поставьте признак - рабочий-нерабочий день, и выполняйте соединений этой таблицы на саму себя по порядковому номеру рабочего дня в месяце.
13 апр 11, 12:56    [10511715]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
Jovanny
Member

Откуда:
Сообщений: 1196
В первом приближении (только нумерация дней недели начинается с воскресенья):

INSERT INTO Table_1 (Id,[Date],[Hours])
SELECT Id, 
	CASE WHEN DATEPART(WEEKDAY, DATEADD(MONTH, 1, [Date])) = 6 THEN DATEADD(DAY, 2, DATEADD(MONTH, 1, [Date])) --суббота
	     WHEN DATEPART(WEEKDAY, DATEADD(MONTH, 1, [Date])) = 1 THEN DATEADD(DAY, 1, DATEADD(MONTH, 1, [Date])) --воскресенье
		 ELSE WHEN DATEPART(WEEKDAY, DATEADD(MONTH, 1, [Date])) BETWEEN 2 AND 6 THEN DATEADD(MONTH, 1, [Date]) END, --другие дни
	[Hours] FROM Table_1 WHERE [Date] BETWEEN '2011-03-01' AND '2011-04-01'
13 апр 11, 13:05    [10511807]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
Jovanny
Member

Откуда:
Сообщений: 1196
Ну, и добавить условия, когда вылезает за последний день месяца.
13 апр 11, 13:09    [10511839]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
Jovanny
Member

Откуда:
Сообщений: 1196
И справочник праздников подсоединить.
13 апр 11, 13:11    [10511860]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
mike909
Member

Откуда:
Сообщений: 662
Jovanny,
В качестве идеи:
declare @t table( Dt datetime )

insert into @t 
select dateadd(day, 0, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 2, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 3, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 4, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 5, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 6, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 7, dateadd(month, -1, GetDate()))
union all
select dateadd(day, 8, dateadd(month, -1, GetDate()))

select 
  dt as [OldData], Datepart(weekday, dt ), 
  dateadd( day, df.df, dateadd(month, 1, dt) ) as [NewData],
  datepart(weekday, dateadd( day, df.df, dateadd(month, 1, dt) ) )
from @t as t
cross apply ( 
  select DatePart(weekday, DateAdd(month, datediff(month, 0, GetDate())-1, 0)) - 
         Datepart(weekday, DateAdd(month, datediff(month, 0, GetDate()), 0)) as [DF]
) df
where Datepart(weekday, dt ) between 2 and 6
--and dt between '2011-03-01' AND '2011-04-01'
?
13 апр 11, 13:15    [10511902]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
syavik
Member

Откуда:
Сообщений: 107
Jovanny,

Огромнейшее Вам :) Будем проверять!
13 апр 11, 13:15    [10511904]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
syavik
Member

Откуда:
Сообщений: 107
mike909,

Спасибо!
13 апр 11, 13:23    [10511986]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
Jovanny
Member

Откуда:
Сообщений: 1196
mike909,

Нет предела совершенству.
Ваш пример более корректный.
13 апр 11, 13:23    [10511993]     Ответить | Цитировать Сообщить модератору
 Re: Начало недели  [new]
Jovanny
Member

Откуда:
Сообщений: 1196
Вот работающий вариант:
DECLARE @OldMonth table (Dt datetime, WorkDayNumber tinyint);
DECLARE @NewMonth table (Dt datetime, WorkDayNumber tinyint);

WITH OldMonth AS ( 
SELECT CAST('2011-03-01' AS datetime) AS Dt
UNION ALL
SELECT DATEADD(DAY, 1, Dt) FROM OldMonth
WHERE Dt < '2011-03-31'
)
INSERT @OldMonth (Dt, WorkDayNumber)
SELECT Dt, ROW_NUMBER() OVER(ORDER BY Dt) FROM OldMonth
WHERE DATEPART(WEEKDAY, Dt) BETWEEN 2 AND 6;

WITH NewMonth AS (
SELECT CAST('2011-04-01' AS datetime) AS Dt
UNION ALL
SELECT DATEADD(DAY, 1, Dt) FROM NewMonth
WHERE Dt < '2011-04-30'
)
INSERT @NewMonth (Dt, WorkDayNumber)
SELECT Dt, ROW_NUMBER() OVER(ORDER BY Dt) FROM NewMonth
WHERE DATEPART(WEEKDAY, Dt) BETWEEN 2 AND 6;

SELECT OM.Dt AS OldDate, NM.Dt AS NewDate FROM @OldMonth AS OM 
INNER JOIN @NewMonth AS NM ON OM.WorkDayNumber = NM.WorkDayNumber
13 апр 11, 14:20    [10512614]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить