If I read your question correctly, you will not be able to actually use the solutions that are higher, which consist of a table of paid and non-paid days, because the 31st is paid unless the entire month has been booked.
I believe this is probably the job for a user-defined function. Starting from the month in which the start date begins and ends with the month in which the end date is located.
CREATE FUNCTION dbo.FN_BillableDays (@StartDate date, @EndDate date) returns int AS BEGIN IF @StartDate > @EndDate BEGIN return null --Error END DECLARE @Next date DECLARE @MonthStart date DECLARE @MonthEnd date DECLARE @NextMonthStart date DECLARE @n int =0 SET @Next = @StartDate SET @MonthStart = DATEADD(day,1-DAY(@Next),@Next) SET @NextMonthStart = DATEADD(month,1,@MonthStart ) SET @MonthEnd = DATEADD(day,-1,@NextMonthStart) WHILE DATEDIFF(month,@Next,@EndDate) >0 BEGIN SET @n = @n + CASE WHEN DAY(@next) = 1 AND DAY(@MonthEnd) = 31 THEN 30 WHEN DAY(@next) = 1 THEN DAY(@MonthEnd) ELSE 1+DAY(@MonthEnd) -DAY(@next) END SET @MonthStart = @NextMonthStart SET @NextMonthStart = DATEADD(month,1,@MonthStart ) SET @MonthEnd = DATEADD(day,-1,@NextMonthStart) SET @Next = @NextMonthStart END --Month of the EndDate SET @n = @n + CASE WHEN DAY(@next) = 1 AND DAY(@EndDate) = 31 THEN 29 WHEN DAY(@next) = 1 THEN DAY(@EndDate)-1 ELSE DAY(@MonthEnd) -DAY(@EndDate) END return @n END
I tried this with some test dates
SELECT b.BookingID, b.StartDate, b.EndDate, dbo.FN_BillableDays (b.StartDate,b.EndDate) AS BillableDays FROM dbo.Booking b
And got the next
BookingID StartDate EndDate BillableDays ----------- ---------- ---------- ------------ 1 2013-12-31 2014-01-02 2 2 2013-12-31 2014-01-30 30 3 2014-01-01 2014-01-30 29 4 2014-01-01 2014-01-31 29 5 2014-01-01 2014-02-01 30 6 2014-01-01 2014-02-02 31 7 2014-02-02 2014-02-01 NULL (7 row(s) affected)
Which is in line with my understanding of the logic you want to implement, but you can configure the last bit that is added on the days of the last month. If they leave on the 31st, you want to give them the last night for free (30-31).
If you do not delete the line WHEN DAY (@next) = 1 AND DAY (@EndDate) = 31 THEN 29