Sql function that returns months and number of days in month in date range

Trying to write a sql table function that will return month and number of days in the month with input parameters of start date and end date

For example, if the input date is 03/22/2015 and end date is 04/12/2015

Would like table returned to be

Month  DaysInMonth
3            10
4             12
johnnyg123Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mike EghtebasDatabase and Application DeveloperCommented:
Create function fn_YearMonthDays(@dt1 date, @dt2 date) returns table
as
Return
select 'Start: ' As StartStop
     , datePart(Year,@dt1) As Y
     , datePart(Month,@dt1) As m
	 , datePart(Day,@dt1) As d
Union select 'Stop: ' As StartStop
     , datePart(Year,@dt2) As Y
     , datePart(Month,@dt2) As m
	 , datePart(Day,@dt2) As d


-- test
declare @dt1 date = '03/22/2015';
declare @dt2 date = '04/12/2015';
Select * from fn_YearMonthDays(@dt1, @dt2);

Open in new window


Produces:

StartStop      Y      m      d
Start:       2015      3      22
Stop:       2015      4      12
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
johnnyg123Author Commented:
Great!!!
0
johnnyg123Author Commented:
Actually

I think I accepted a bit prematurely

I mentioned that I wanted days and months for all months in the period

If I try

-- test
declare @dt1 date = '03/22/2015';
declare @dt2 date = '05/12/2015';
Select * from fn_YearMonthDays(@dt1, @dt2);

I get

StartStop      Y      m      d
Start:       2015      3      22
Stop:       2015      5      12

In this scenario I would want

StartStop      Y      m      d
Start:       2015      3      22
                2015       4      30
Stop:       2015      5      12
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

Mike EghtebasDatabase and Application DeveloperCommented:
re:> I mentioned that I wanted days and months for all months in the period

I read the original question again but I didn't see all months.

I am sure this is what you had in mind but you have stated a bit differently. You always can add a new question asking for the changes.

Mike
0
johnnyg123Author Commented:
No worries I figured it out
0
johnnyg123Author Commented:
In case any one is following this post

here is what I figured out

(added some additional functionality to allocate cost)

ALTER FUNCTION [dbo].[fnAllocateCampaignCosts] (@FromDate DATETIME,@EndDate DATETIME,@Amount Decimal(18,2))
RETURNS @tblResults TABLE([Year] INT, [Month] INT, [Days] INT,AllocationAmount decimal(18,2))
AS
BEGIN
     
         
   DECLARE @DAYS INT
   DECLARE @Months INT
   Declare @AmountPerDay decimal(18,2)

      DECLARE      @StartDay INT, @StartMonth INT, @StartYear INT, @EndDay INT, @EndMonth INT, @EndYear INT
      SELECT      @StartDay = DAY(@FromDate), @StartMonth = MONTH(@FromDate), @StartYear = YEAR(@EndDate),
                  @EndDay = DAY(@EndDate), @EndMonth = MONTH(@EndDate), @EndYear = YEAR(@EndDate)

      DECLARE      @LastDayOfMonth INT

      WHILE (@StartYear < @EndYear) OR (@StartMonth <= @EndMonth AND @StartYear = @EndYear)
      BEGIN
            -- Find last Day of current Month
            SELECT      @LastDayOfMonth = CASE
                              WHEN @StartYear = @EndYear AND @StartMonth = @EndMonth THEN @EndDay
                              WHEN @StartMonth IN (1, 3, 5, 7, 8, 10, 12) THEN 31
                              WHEN @StartMonth IN (4, 6, 9, 11) THEN 30
                              ELSE CASE
                                    WHEN (@StartYear % 4) = 0 THEN 29 ELSE 28
                              END
                        END

            -- Calculate number of Days of current Month and insert to result table
            INSERT      @tblResults([Year] , [Month], [Days])
            VALUES      (
                  @StartYear,
                  @StartMonth,
                  @LastDayOfMonth - @StartDay + 1
            )
            
            -- Next month
            SELECT      @StartYear = CASE WHEN @StartMonth = 12 THEN @StartYear + 1 ELSE @StartYear END,
                        @StartMonth = CASE WHEN @StartMonth = 12 THEN 1 ELSE @StartMonth + 1 END,
                        @StartDay = 1 -- Reset to 1 for next Month
      END

      --Select * from @tblResults where month = '02'

      --SELECT  @Days = (Select days from @tblResults where month = @Month)
 --Return  @Days

      -- Select result

      set @Days = (Select sum(days) from @tblResults)
      set @months = (Select count(month) from @tblResults)

      set @AmountPerDay = @Amount/@Days

      Update @tblResults  set AllocationAmount =  case when @months = 1 then @Amount Else  @AmountPerDay * [Days] end



Return
END
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft SQL Server 2008

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.