I'd start with a table that contains the date and some convenience columns plus a workday indicator. (date full db date column, day, month, year, day_of_week, work_day Y/N field, isvacation, isweekday).
Populate that with values in the time range you're going to use. Set appropriate flags (e.g. update date_table set isweekday where day_of_week between 1 and 5) and update all the work_day and isvacation flags by vacation that your company observes. This is going to be a manual process, but not daunting. Some holidays are the same day each year, some are not. A vacation day could fall on the weekend, but be observed the previous Friday, etc.
Then you can calculate work hours pretty easily (e.g. select count(1)*8 from date_table where month = 1 and year = 2014 and work_day = 'Y'
Once the table is created, you can use it for lots of stuff. Add a quarter field, first work day of the month field, day names, month names, etc.. Pretty handy, especially for reporting, just join on the truncated date column in your source data to the date field in the table.
This will do it:
DECLARE @d DATE = '20140502', @dm TINYINT = 26;
DECLARE @Start_Of_Fiscal_Month DATE
SET @Start_Of_Fiscal_Month = DATEADD(DAY, @dm-1, DATEADD(MONTH, -1 + DATEPART(dd, @d)/26, DATEADD(DAY, 1-DAY(@d), @d)));
SELECT @Start_Of_Fiscal_Month
SELECT DATEDIFF(dd, @Start_Of_Fiscal_Month, @d) + 1
Best Answer
You can use generate_series() to generate a series of dates, and extract() to get day of week.
Then simply filter those dates where day of week are not 0=Sunday, 6=Saturday.
dbfiddle here
If you have to exclude public holidays and other non-business days, you can build a
business_day
table. Just insert the output from above and then remove all days that have to be excluded (in certain countries, like Hungary, there might be additional replacement days (typically Saturdays) which have to be added, too). Of course, this has to be maintained (for example, you can prepare the next year every December), but as there is no built-in functionality that knows about those days, you have no better option.Using a calendar table
Let me create a sample
calendar
table and insert some values:Now you can use a function to obtain the next Nth business day in this way:
or
Both return same result:
db<>fiddle here