查找主题日期之间的工作日数

时间:2014-05-02 07:06:20

标签: sql sql-server sql-server-2008 stored-procedures

我在桌子上有一个学校的时间表。我也知道学校的startDate和endDate。表结构如下:

SubjectsToDay

Subject  | Day
---------------------
Maths    | Monday
Physics  | Tuesday
Chemistry| Wednesday
Maths    | Thursday
Biology  | Friday

假日

Date        | Reason
----------------------------
2014-01-26  | Republic day
2014-05-01  | Labour's day
2014-06-04  | Reason1
2014-07-04  | Reason2
2014-07-14  | Reason3
2014-08-14  | Reason4
2014-09-14  | Reason5
2014-10-12  | Reason6

我想计算一个特定主题的工作天数(输入,比方说数学)。 工作日不应考虑Holidays表中给出的假期。我想在存储过程中执行此操作,该过程以StartDate,EndDate和Subject作为参数。我怎样才能有效地纠正这个问题?

P.S.-假期表不固定,可以在此

中添加或删除任何行

2 个答案:

答案 0 :(得分:1)

使用cte获取所有日期,加入主题以计算课程数量并加入假期以排除它们:

declare @startdate date;
set @startdate = '2014-01-01';
declare @enddate date;
set @enddate = '2014-12-31'

;with DateRange AS
(
    SELECT 
        @startdate as DateValue
    UNION ALL
    SELECT 
        dateadd(dd,1,DateValue)
    FROM   DateRange
    WHERE  dateadd(dd,1,DateValue) <= @enddate
)
select 
        s.Name
      , COUNT(*)
from    DateRange d
join    SubjectsToDay s
on      DATENAME(dw,d.DateValue) = s.Day
left outer join 
        Holidays h
on      d.DateValue = h.Date
where   h.Reason is null
group by
        s.Name
option (maxrecursion 365)

答案 1 :(得分:0)

大多数人会为此使用日历表,但这里的计算应该给出相同的结果。我建议你把它与你的环境合并后把它放到存储过程中。

-- your parameters
DECLARE @from date = '2014-01-01', @to date = '2014-01-01'
DECLARE @Subjectname varchar(15) = 'Chemistry'

-- variable declarations
DECLARE @d int
DECLARE @holiday TABLE(Date date, Reason varchar(20))
DECLARE @subject TABLE(Name varchar(15), Day varchar(10))

-- mapping day to numeric value

;WITH x as
(
SELECT CASE Day WHEN 'Monday' THEN 2
                WHEN 'Tuesday' THEN 3
                WHEN 'Wednesday' THEN 4
                WHEN 'Thursday' THEN 5
                WHEN 'Friday' THEN 6
-- allowing weekends for solving similar questions 
                WHEN 'Saturday' THEN 7
                WHEN 'Sunday' THEN 1 END daynumber
FROM SubjectsToDay
WHERE Subject = @Subjectname
)
SELECT 
-- number of chosen days between from and to
-- subtract holidays from same day between from and to
SUM(datediff(week, dateadd(d, -daynumber, @from), 
                   dateadd(d, 1-daynumber, @to))
    -y.cnt)
FROM X
CROSS APPLY
( SELECT count(*) cnt FROM Holidays WHERE datediff(d, -1, Date ) %7 + 1 = daynumber
  AND Date between @from and @to) y