我创建了以下脚本来更新Microsoft SQL Server中的计划表。主键字段是日期时间,是日历上的各个日期。员工安排连续7天,我需要在每个星期一到星期日到年底之间的两个雇员之间轮换7天。我使用循环创建了以下脚本,并且正在寻找一种方法来完成它而不使用循环。谢谢!
DECLARE @z_start INT
DECLARE @z_date DATETIME
SET @z_date = '03/07/16'
WHILE(@z_date < '12/31/16')
BEGIN
SET @z_start = 0
WHILE(@z_start < 7) BEGIN
UPDATE EmployeeOnCall
SET employeeName = 'Jones, Jim'
WHERE deptID = 25 AND weekDay = @z_date
SET @z_date = DATEADD(dd, 1, @z_date)
SET @z_start = @z_start + 1
END
SET @z_start = 0
WHILE(@z_start < 7) BEGIN
UPDATE EmployeeOnCall
SET employeeName = 'Penton, Andy'
WHERE deptID = 25 AND weekDay = @z_date
SET @z_date = DATEADD(dd, 1, @z_date)
SET @z_start = @z_start + 1
END
END;
答案 0 :(得分:0)
您可以使用DATEPART
和CTE执行此操作。这是相关部分:
;with wkNum as (
SELECT weekDay, EmployeeName, deptID, (DATEPART(wk, weekDay) / 2) % 2 as period
FROM EmployeeOnCall
)
UPDATE wkNum
SET employeename = CASE WHEN wkNum.period = 0 THEN 'Jones, Jim' ELSE 'Penton, Andy' END
这个想法是确定一年中的哪一周,将其除以2,然后按照您正在处理的员工数量对其进行模数化。 这是一个测试脚本:
DECLARE @test TABLE (weekDay datetime, employeename varchar(50), deptID int);
DEClARE @startdate datetime = '2016-02-16';
declare @enddate datetime = '2016-12-31';
;with
N0 as (SELECT 1 as n UNION ALL SELECT 1)
,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
INSERT @test (weekDay, deptID)
SELECT DATEADD(day,num-1,@startdate) as thedate, 25
FROM nums
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
;with wkNum as (
SELECT weekDay, EmployeeName, deptID, (DATEPART(wk, weekDay) / 2) % 2 as period FROM @test
)
UPDATE wkNum
SET employeename = CASE WHEN wkNum.period = 0 THEN 'Jones, Jim' ELSE 'Penton, Andy' END
SELECT * FROM @test
如果你有一张员工表,可以像这样扩展:
DECLARE @emps TABLE (Name varchar(100));
INSERT @emps VALUES ('Dan'), ('Joe'), ('Asdf')
UPDATE eoc
SET employeename = emp.Name
FROM EmployeeOnCall eoc
INNER JOIN (SELECT ROW_NUMBER() OVER(ORDER BY Name) rn, Name FROM @emps) emp
ON ((DATEPART(wk, weekDay) / 2) % (SELECT COUNT(*) FROM @emps)) + 1 = emp.rn
答案 1 :(得分:0)
最佳方法是填充持久性Calendar
表。填写10年开始的日期列表,将每天标记为工作日或周末日,附加您需要的任何列。并且只需加入它,按照您获得的边缘日期进行过滤。
您的案例并未说明您提到7天间隔的原因。 7天意味着每一天。假设您有@startdate
和@enddata
个变量。让我们生成日期列表并将其与目标表连接。
declare
@startdate datetime = '20150612',
@enddate datetime = '20160122',
@period_len int
set @period_len = datediff(dd, @startdate, @enddate)
;with cteCounter as
(
select top (@period_len)
ROW_NUMBER() OVER(ORDER BY c.object_id) as counter
from sys.columns c
cross join sys.columns cc
order by counter
),
cteCalendar as
(
select c.counter, dateadd(dd, c.counter-1, @startdate) as calendar_date
from cteCalendar c
order by calendar_date
)
UPDATE e SET
employeeName = 'Jones, Jim'
FROM EmployeeOnCall e
inner join cteCalendar c on c.calendar_date = e.weekDay
WHERE e.deptID = 25