可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How can I calculate the number of work days between two dates from table (from the 1st row to the end) in SQL Server 2008?
I tried something like this, but it does not work
DECLARE @StartDate as DATETIME, @EndDate as DATETIME Select @StartDate = date2 from testtable ; select @EndDate = date1 from testtable ; SELECT (DATEDIFF(dd, @StartDate, @EndDate) + 1) -(DATEDIFF(wk, @StartDate, @EndDate) * 2) -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
回答1:
I would always recommend a Calendar table, then you can simply use:
SELECT COUNT(*) FROM dbo.CalendarTable WHERE IsWorkingDay = 1 AND [Date] > @StartDate AND [Date]
Since SQL has no knowledge of national holidays for example the number of weekdays between two dates does not always represent the number of working days. This is why a calendar table is a must for most databases. They do not take a lot of memory and simplify a lot of queries.
But if this is not an option then you can generate a table of dates relatively easily on the fly and use this
SET DATEFIRST 1; DECLARE @StartDate DATETIME = '20131103', @EndDate DATETIME = '20131104'; -- GENERATE A LIST OF ALL DATES BETWEEN THE START DATE AND THE END DATE WITH AllDates AS ( SELECT TOP (DATEDIFF(DAY, @StartDate, @EndDate)) D = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.Object_ID), @StartDate) FROM sys.all_objects a CROSS JOIN sys.all_objects b ) SELECT WeekDays = COUNT(*) FROM AllDates WHERE DATEPART(WEEKDAY, D) NOT IN (6, 7);
EDIT
If you need to calculate the difference between two date columns you can still use your calendar table as so:
SELECT t.ID, t.Date1, t.Date2, WorkingDays = COUNT(c.DateKey) FROM TestTable t LEFT JOIN dbo.Calendar c ON c.DateKey >= t.Date1 AND c.DateKey
Example on SQL-Fiddle
回答2:
This does it excluding the days out but date part rather than description. You can substitute the parameters used as an example for the values in your query.
Declare @startdate datetime = '2013-11-01', @enddate datetime = '2013-11-11' SELECT (DATEDIFF(dd, @StartDate, @EndDate) + 1) -(DATEDIFF(wk, @StartDate, @EndDate) * 2) -(case datepart(dw, @StartDate)+@@datefirst when 8 then 1 else 0 end) -(case datepart(dw, @EndDate)+@@datefirst when 7 then 1 when 14 then 1 else 0 end) Returns 7
回答3:
To add to GarethD's answer - I put together the SQL for a USA version of the Calendar table, with all holidays and weekends set to is_working_day = false... for anyone that would like the SQL, here it is:
declare @start_dt as date = '1/1/2009'; -- Date from which the calendar table will be created. declare @end_dt as date = '1/1/2030'; -- Calendar table will be created up to this date (not including). create table CalendarTable ( date_id date primary key, date_year smallint, date_month tinyint, date_day tinyint, weekday_id tinyint, weekday_nm varchar(10), month_nm varchar(10), day_of_year smallint, quarter_id tinyint, first_day_of_month date, last_day_of_month date, start_dts datetime, end_dts datetime, week_number_of_month int, is_working_day bit, ) while @start_dt