我有两张桌子,一张项目表和一张日历表。第一个包含一个开始日期和所需的日期。日历表包含通常的日期信息,例如日期,dayofweek,以及列是工作日,显示该日是星期六,星期日或银行假日(值= 0)还是常规工作日(值= 1)。 / p>
对于某个报告,我需要编写一个存储过程,通过添加所需的估计工作日数来计算预测的最终日期。
示例:
**Projects**
Name Start_Planned Work_days_Required
Project A 02.05.2016 6
Calendar (04.05 is a bank holdiday)
Day Weekday Workingday
01.05.2016 7 0
02.05.2016 1 1
03.05.2016 2 1
04.05.2016 3 0
05.05.2016 4 1
06.05.2016 5 1
07.05.2016 6 0
08.05.2016 7 0
09.05.2016 1 1
10.05.2016 2 1
假设所需的估计天数为6(这导致预测的结束日期为10.05.2016)。是否可以以某种方式加入表格,这样我就可以添加类似
的内容select date as enddate_predicted
from calendar
join projects
where number_of_days = 6
我会发布一些更多的代码,但我完全不知道从哪里开始。
谢谢!
答案 0 :(得分:1)
您可以在第一次约会后的所有工作日内完成,然后应用ROW_NUMBER()
获取每个日期的天数:
SELECT Date, DayNum = ROW_NUMBER() OVER(ORDER BY Date)
FROM Calendar
WHERE IsWorkingDay = 1
AND Date >= @StartPlanned
然后它只是第6天过滤的情况:
DECLARE @StartPlanned DATE = '20160502',
@Days INT = 6;
SELECT Date
FROM ( SELECT Date, DayNum = ROW_NUMBER() OVER(ORDER BY Date)
FROM Calendar
WHERE WorkingDay = 1
AND Date >= @StartPlanned
) AS c
WHERE c.DayNum = @Days;
这不是问题的一部分,但是对于将来的验证,使用OFFSET/FETCH
DECLARE @StartPlanned DATE = '20160502',
@Days INT = 6;
SELECT Date
FROM dbo.Calendar
WHERE Date >= @StartPlanned
AND WorkingDay = 1
ORDER BY Date
OFFSET (@Days - 1) ROWS FETCH NEXT 1 ROWS ONLY
<强>附录强>
我之前错过了关于另一张桌子的部分,关于将它放入光标的评论促使我修改了我的答案。我会在您的日历表中添加一个名为WorkingDayRank
的新列:
ALTER TABLE dbo.Calendar ADD WorkingDayRank INT NULL;
GO
UPDATE c
SET WorkingDayRank = wdr
FROM ( SELECT Date, wdr = ROW_NUMBER() OVER(ORDER BY Date)
FROM dbo.Calendar
WHERE WorkingDay = 1
) AS c;
这可以在运行中完成,但是当它存储为值时,您将获得更好的性能,然后您的查询变为:
SELECT p.Name,
p.Start_Planned,
p.Work_days_Required,
EndDate = c2.Date
FROM Projects AS P
INNER JOIN dbo.Calendar AS c1
ON c1.Date = p.Start_Planned
INNER JOIN dbo.Calendar AS c2
ON c2.WorkingDayRank = c1.WorkingDayRank + p.Work_days_Required - 1;
这只是获取开始日期的工作日排名,并通过加入WorkingDayRank
(-1因为您希望结束日期包括范围)来查找项目指定的前几天数
如果你计划在非工作日开始你的项目,这将失败,所以一个更强大的解决方案可能是:
SELECT p.Name,
p.Start_Planned,
p.Work_days_Required,
EndDate = c2.Date
FROM Projects AS P
CROSS APPLY
( SELECT TOP 1 c1.Date, c1.WorkingDayRank
FROM dbo.Calendar AS c1
WHERE c1.Date >= p.Start_Planned
AND c1.WorkingDay = 1
ORDER BY c1.Date
) AS c1
INNER JOIN dbo.Calendar AS c2
ON c2.WorkingDayRank = c1.WorkingDayRank + p.Work_days_Required - 1;
这使用CROSS APPLY
在项目开始日期或之后获得下一个工作日,然后应用与之前相同的连接。
答案 1 :(得分:1)
此查询返回一个表,其中包含每个项目的预测enddate
select name,min(day) as predicted_enddate from (
select c.day,p.name from dbo.Calendar c
join dbo.Calendar c2 on c.day>=c2.day
join dbo.Projects p on p.start_planned<=c.day and p.start_planned<=c2.day
group by c.day,p.work_days_required,p.name
having sum(c2.workingday)=p.work_days_required
) a
group by name
答案 2 :(得分:0)
- 这给了我关于所有项目的信息
select p.projectname,p.Start_Planned ,c.date,
from calendar c
join
projects o
on c.date=dateadd(days,p.Work_days_Required,p.Start_Planned)
and c.isworkingday=1
现在你可以使用如下的CTE或将其包装在一个程序
中
;with cte
as
(
Select
p.projectnam
p.Start_Planned ,
c.date,datediff(days,p.Start_Planned,c.date) as nooffdays
from calendar c
join
projects o
on c.date=dateadd(days,p.Work_days_Required,p.Start_Planned)
and c.isworkingday=1
)
select * from cte where nooffdays=6
答案 3 :(得分:0)
使用以下逻辑
"DATE","TIME","IP","LOOKING_FOR"
"2016-05-22","07:30:40","XX.XX.XX.XX","/site.php?=dTM_c1_uid7"
"2016-05-22","07:31:10","XX.XX.XX.XX","/site.php?=dTM_c1_uid7"
"2016-05-22","07:31:19","XX.XX.XX.XX","/site.php?=dTM_c1_uid8"