Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Complete months SQL function

Author  Topic 

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 06:25:34
Greetings!

How are you guys doing?! Hope you're all keeping well! Anyway, on to my problem.

I am trying to write a SQL Server function that would take two dates and work out the complete months but I am struggling!!

Example :
04/02/2004 to 03/03/2004 is one complete month whereas 04/02/2004 to 02/03/2004 is not. The start date is where the month count should begin and I am only interested in complete months.

Your advise would be much appreciated.

Thanks in advance.

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution

mr_mist
Grunnio

1870 Posts

Posted - 2005-03-16 : 06:42:08
How are you determining what a complete month is? I'm not sure why the first one is a complete month but the second is not?

Can you use datediff with a number of days?

-------
Moo. :)
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 07:10:32
quote:
Originally posted by mr_mist

How are you determining what a complete month is? I'm not sure why the first one is a complete month but the second is not?

Can you use datediff with a number of days?

-------
Moo. :)



In business terms, the second one isn't a complete month.

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-16 : 07:19:35
it could probably be very simplified, but this is the first thing that comes to mind

if day(@startDate) = day(@EndDate)-1 and month(@startDate) = month(@EndDate)-1 and
(year(@startDate) = year(@EndDate) or year(@startDate) = year(@EndDate)-1) then
return 1
else
return 0

Go with the flow & have fun! Else fight the flow
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 07:31:28
quote:
Originally posted by spirit1

it could probably be very simplified, but this is the first thing that comes to mind

if day(@startDate) = day(@EndDate)-1 and month(@startDate) = month(@EndDate)-1 and
(year(@startDate) = year(@EndDate) or year(@startDate) = year(@EndDate)-1) then
return 1
else
return 0

Go with the flow & have fun! Else fight the flow



Nice try but doesn't work since 04/02/2004 to 03/03/2004 is a complete month (please check your calendar if you want to understand what I mean by complete month).

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-16 : 07:38:47
so wouldn't that be solved by just subtracting 2 from Day(@endDate) ??

Go with the flow & have fun! Else fight the flow
Go to Top of Page

mr_mist
Grunnio

1870 Posts

Posted - 2005-03-16 : 07:48:07
Do you mean a block of four weeks? If so, can you just say that a difference of 28 days or more is a complete month?

Otherwise I don't know what you mean.

-------
Moo. :)
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-16 : 07:52:16
i think he means that the "month" is defined by:
day N, month M
to
day N-1, month M+1

so day N, month M+1 is alread in the next month.


Go with the flow & have fun! Else fight the flow
Go to Top of Page

madhivanan
Premature Yak Congratulator

22864 Posts

Posted - 2005-03-16 : 08:48:46
Slightly modified code of spirit1


declare @startDate datetime
set @startDate = '4-jan-2004 01:00:00'
declare @endDate datetime
set @endDate = '3-feb-2004 02:22:40'

if ((day(@startDate)-1 = day(@EndDate) and month(@startDate) = month(@EndDate)-1) or
(month(@startDate)=1 and day(@startDate)=31 and month(@EndDate)=2 and (day(@EndDate)=28 or day(@EndDate)=29)))and
(year(@startDate) = year(@EndDate) or year(@startDate) = year(@EndDate)-1)
select 1
else
select 0


Madhivanan

Failing to plan is Planning to fail
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2005-03-16 : 08:58:35
is this what you need?

select case when @EndDate = DateAdd(m,@StartDate,1)-1 then 1 else 0 end

you need to give us more specific information. Instead of us trying to guess what you are looking for, you need to explicitly specify it.

- Jeff
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2005-03-16 : 09:28:44
From your example, it is not obvious the exact date format you are using. Is you data fomat DD/MM/YYYY? If so, you should say that, because most people from the US will assume MM/DD/YYYY when they see a date written that way.

As the other people said, you need to give your exact definition of a month, bacause a month is not an exact thing. For example, is 2005/01/31 through 2005/02/28 a full month? It might be clearer if you showed more examples, say the end month day for the whole month of 2005/01/01 through 2005/01/31.


quote:
Originally posted by Amethystium
...Example :
04/02/2004 to 03/03/2004 is one complete month whereas 04/02/2004 to 02/03/2004 is not. The start date is where the month count should begin and I am only interested in complete months...



CODO ERGO SUM
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 09:44:34
quote:
Originally posted by spirit1

i think he means that the "month" is defined by:
day N, month M
to
day N-1, month M+1

so day N, month M+1 is alread in the next month.


Go with the flow & have fun! Else fight the flow



If my start date is 01/02/2003 and my end date is 16/10/2003 then the sequence of dates (in order to work out the complete months) would be something like :

01/02/2003 28/02/2003
01/03/2003 31/03/2003
01/04/2003 30/04/2003
01/05/2003 31/05/2003
01/06/2003 30/06/2003
01/07/2003 31/07/2003
01/08/2003 31/08/2003
01/09/2003 31/09/2003
01/10/2003 ..........

So the answer would be 8 complete months

Hope this makes sense!

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2005-03-16 : 09:51:18
what is the answer? 8? or a list of start/end dates within that time period? What do you want returned?

- Jeff
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-16 : 09:54:02
so then this is ok?

declare @startdate datetime, @EndDate datetime
--select @startdate = '01/02/2003', @EndDate = '22/10/2003'
select @startdate = '02/02/2003', @EndDate = '22/10/2003'

select datediff(m, @startdate, @EndDate) as IncorrectDiff,
case when day(@startdate) = 1 then datediff(m, @startdate, @EndDate) else datediff(m, @startdate, @EndDate)-1 end as CorrectDiff



Go with the flow & have fun! Else fight the flow
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 10:05:15
quote:
Originally posted by jsmith8858

what is the answer? 8? or a list of start/end dates within that time period? What do you want returned?

- Jeff



Yes I want the number of complete months.

Spirit, thanks for the query but it returns 0 when I input 04/02/2003 and 03/03/2003 even though it is a complete month (note that both end dates should be included).

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2005-03-16 : 10:18:40
I have read you posts several times, and I have to say that you have not made it clear what your definition of a "complete month" is and what output you are expecting to see. Until you do that, it will difficult for anyone to help you.


quote:
Originally posted by Amethystium
...Yes I want the number of complete months.

Spirit, thanks for the query but it returns 0 when I input 04/02/2003 and 03/03/2003 even though it is a complete month (note that both end dates should be included)....


CODO ERGO SUM
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 10:27:54
quote:
Originally posted by Michael Valentine Jones

I have read you posts several times, and I have to say that you have not made it clear what your definition of a "complete month" is and what output you are expecting to see. Until you do that, it will difficult for anyone to help you.


quote:
Originally posted by Amethystium
...Yes I want the number of complete months.

Spirit, thanks for the query but it returns 0 when I input 04/02/2003 and 03/03/2003 even though it is a complete month (note that both end dates should be included)....


CODO ERGO SUM



Sorry about that... I am trying to write up a new message explaining exactly what I am trying to achieve.

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-16 : 12:05:45
quote:
Originally posted by Michael Valentine Jones

I have read you posts several times, and I have to say that you have not made it clear what your definition of a "complete month" is and what output you are expecting to see. Until you do that, it will difficult for anyone to help you.


quote:
Originally posted by Amethystium
...Yes I want the number of complete months.

Spirit, thanks for the query but it returns 0 when I input 04/02/2003 and 03/03/2003 even though it is a complete month (note that both end dates should be included)....


CODO ERGO SUM



Not to worry, here is the final solution (eventually figured it out)... and it works for leap years as well. Thanks.


if exists (select * from information_schema.tables where table_name = 'mdays')
drop table dbo.mdays
go

create table dbo.mdays (
monthNumber int identity(1, 1),
monthDays int
)

insert into dbo.mdays (monthDays)
select 31 union all
select 28 union all
select 31 union all
select 30 union all
select 31 union all
select 30 union all
select 31 union all
select 31 union all
select 30 union all
select 31 union all
select 30 union all
select 31
go

if exists (select * from sysobjects where name = 'fn_Xndays_in_mth' and type = 'FN')
drop function dbo.fn_Xndays_in_mth
go

create function dbo.fn_Xndays_in_mth (@mth int, @yr int)
returns smallint as

begin

declare @OffSet int
declare @theResult int

set @theResult = 0
set @OffSet = 0

if @mth = 2
begin
if (@yr%4 = 0 and @yr%100 <> 0) or @yr%1000 = 0
begin
set @Offset = 1
end
else
set @Offset = 0
end

set @theResult = (select monthDays from mdays where monthNumber = @mth) + @Offset

return @theResult

end

-- Main function

if exists (select * from sysobjects where name = 'fn_Complete_Months' and type = 'FN')
drop function dbo.fn_Complete_Months
go

create function dbo.fn_Complete_Months (@Dst datetime, @DEnd datetime)
returns smallint as

begin

declare @Offset int

set @Offset = 0

if day(@Dst) = 1 and day(@DEnd) = dbo.fn_Xndays_in_mth(month(@DEnd), year(@DEnd))
begin
set @Offset = 1
end
else
if day(@Dst) > day(@DEnd) + 1
begin
set @Offset = -1
end

return (year(@DEnd) - year(@Dst)) + (month(@DEnd) - month(@Dst) + @Offset)

end


Example :


select dbo.fn_Complete_Months(convert(datetime, '04/02/2003', 103), convert(datetime, '03/06/2003', 103))


Covering the period :

-- 04/02/2003 03/03/2003
-- 04/03/2003 03/04/2003
-- 04/04/2003 03/05/2003
-- 04/05/2003 03/06/2003

returns 4 complete months, however if you change the end date to 02/06/2003 the function returns just 3 months. Oh and by the way, the date format is dd/mm/yyyy

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-16 : 12:34:09
you got you leap year algorithm wrong...

Go with the flow & have fun! Else fight the flow
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2005-03-16 : 16:45:13
You can compute the number of days in a month directly using SQL functions, without using a table:
declare @theResult int
declare @mth int,
@yr int

select @yr = 2004
select @mth = 2

select @theResult =
day(dateadd(dd,-1,dateadd(mm,@mth,dateadd(yy,@yr-1900,0))))

select @theResult

However, there is no reason to extract the Year and Month to get the total days in a month, because you can compute it directly from a datetime value:
declare @dt	datetime
select @dt = '2004/02/29'

select day(dateadd(dd,-1,dateadd(mm,datediff(mm,0,@dt)+1,0)))


Have you really tested your code? For example, the following produced a value of -7 when I ran it. From what I could tell, I believe you would want a value of 4.
declare @Dst datetime, @DEnd datetime
select @Dst = '2002/12/04'
select @DEnd = '2003/04/04'

select dbo.fn_Complete_Months(@Dst,@DEnd)


This produced the result I believe you are looking for, 4:
declare @Dst datetime, @DEnd datetime
select @Dst = '2002/12/04'
select @DEnd = '2003/04/04'

select Full_Months =
datediff(mm,dateadd(mm,datediff(mm,0,@Dst),0),
dateadd(mm,datediff(mm,0,@DEnd),0))-1
+
case
when day(@Dst) = 1 and
day(@DEnd) =
-- Days in the month
day(dateadd(dd,-1,dateadd(mm,datediff(mm,0,@DEnd)+1,0)))
then 2
when day(@Dst) > day(@DEnd) + 1
then 0
else 1
end




CODO ERGO SUM
Go to Top of Page

Amethystium
Aged Yak Warrior

701 Posts

Posted - 2005-03-17 : 05:00:54
quote:
Originally posted by Michael Valentine Jones

You can compute the number of days in a month directly using SQL functions, without using a table:
declare @theResult int
declare @mth int,
@yr int

select @yr = 2004
select @mth = 2

select @theResult =
day(dateadd(dd,-1,dateadd(mm,@mth,dateadd(yy,@yr-1900,0))))

select @theResult

However, there is no reason to extract the Year and Month to get the total days in a month, because you can compute it directly from a datetime value:
declare @dt	datetime
select @dt = '2004/02/29'

select day(dateadd(dd,-1,dateadd(mm,datediff(mm,0,@dt)+1,0)))


Have you really tested your code? For example, the following produced a value of -7 when I ran it. From what I could tell, I believe you would want a value of 4.
declare @Dst datetime, @DEnd datetime
select @Dst = '2002/12/04'
select @DEnd = '2003/04/04'

select dbo.fn_Complete_Months(@Dst,@DEnd)


This produced the result I believe you are looking for, 4:
declare @Dst datetime, @DEnd datetime
select @Dst = '2002/12/04'
select @DEnd = '2003/04/04'

select Full_Months =
datediff(mm,dateadd(mm,datediff(mm,0,@Dst),0),
dateadd(mm,datediff(mm,0,@DEnd),0))-1
+
case
when day(@Dst) = 1 and
day(@DEnd) =
-- Days in the month
day(dateadd(dd,-1,dateadd(mm,datediff(mm,0,@DEnd)+1,0)))
then 2
when day(@Dst) > day(@DEnd) + 1
then 0
else 1
end




CODO ERGO SUM



Yes you are right. I thought my function was actually working because the values I did use to test seemed to work. Perhaps I should've spent more time on it but it was near to going home time so I just posted it my answer and went home.

I will be using your code for my calculation.

Once again, cheers!

------------->>> BREAKING NEWS!!! <<<-------------
Saddam Hussien has weapons of mass destrcution
Go to Top of Page
    Next Page

- Advertisement -