February 17, 2006 at 5:32 am
Sergiy, I believe the following is correct:
select case when
Datediff(dd, @startDate, @endDate - (@@Datefirst+Datepart(dw,@endDate)-2) %7) < 0
then 0 else
Datediff(dd, @startDate, @endDate - (@@Datefirst+Datepart(dw,@endDate)-2) %7) / 7 + 1
end
The division and modulo operations behave strangely for negative numbers, I think. E.g
select (-1)/7
select (-1) % 7
is 0 and -1, respectively. I would expect it to be -1 and 6, respectively, and then your posted formula would work.
February 17, 2006 at 6:21 am
There is no way to get (-1)%7 in my formula.
Both @@Datefirst and Datepart(dw,@endDate) are positive values, their SUM is >= 2.
And for both dtes '2005-12-31' it returns 0 which is right - no Mondays between Saturday 31/12/2005 and Saturday 31/12/2005.
But one thing I missed when copied script here:
@StartDate must be shifted to Previous Monday as well:
select Datediff(dd,
@StartDate - (@@Datefirst+Datepart(dw,@StartDate)-2) %7,
@EndDate - (@@Datefirst+Datepart(dw,@EndDate)-2) %7)
/ 7
_____________
Code for TallyGenerator
February 17, 2006 at 6:35 am
What I meant was that you could easily get (-1)/7, although this wasn't clear from what I wrote.
I assumed you wanted to add 1 to the formula you stated perviously. Anyway, it seems to return 0 whenever the two dates are the same.
I think this is also the case with your new formula - you always get 0 when the two dates are the same
February 17, 2006 at 6:51 am
I mean get (-1)%7, not get (-1)/7
And what you expect to get when 2 dates are the same?
There are no Mondays between them, so it must be 0.
What's wrong with that?
_____________
Code for TallyGenerator
February 17, 2006 at 7:26 am
I see. No, nothing's wrong. You include the second date but not the first. I thought you included both dates (like I do in my query). I apologize, your query works perfectly.
But... I think my query is slightly faster (replace '19000102' by '19000101' to get the same output as your query).
February 17, 2006 at 6:26 pm
My query does not depend on DATEFIRST settings.
_____________
Code for TallyGenerator
February 18, 2006 at 5:40 am
So I've noticed - neither does mine
February 18, 2006 at 11:54 pm
What about server collation?
_____________
Code for TallyGenerator
February 19, 2006 at 12:12 am
And you formula returns 1 Monday between '2005-02-19' and '2006-02-20' and between '2006-02-20' and '2006-02-21'.
This Monday is included in both periods. Sounds not right.
_____________
Code for TallyGenerator
February 20, 2006 at 1:03 am
My formula
datediff(d, '19000101', @dateTo)/7 - datediff(d, '19000102', @dateFrom)/7
doesn't depend on datefirst settings and server collation. Like I have said before, it returns the number of Mondays between @dateFrom and @dateTo, both days inclusive. '2006-02-20' is a Monday, as far as I know, and therefore it will return 1 for both periods.
If you insist on not including the first date (but still including the second date), my formula is easily modified:
datediff(d, '19000101', @dateTo)/7 - datediff(d, '19000101', @dateFrom)/7
I have tested that this formula has the same output as your formula for every single day of the year 2005 (365*365 test cases), so I guess both are correct. My formula, however, performs slightly better than your formula - at least, that was what I concluded in my test.
February 20, 2006 at 2:58 am
Sorry, I was looking on another your formula.
_____________
Code for TallyGenerator
February 20, 2006 at 3:08 am
Yes, the first one wasn't correct for dates after '20060213', as Jeff Moden pointed out. My present formula isn't correct for dates before '19000101', but I guess that's all right
January 14, 2010 at 9:39 am
Hi - great posting and answers... I realize the posts are quite old - but hoping some of you experts are still available out here.
I used the counting method in crystal reports and it seems pretty good- but I am intrigued by the formula. But - when I try the formula I do not get the same results.
I am using the date range 2009-03-01 to 2009-03-31. Should have 5 Sundays, Mondays, Tuesdays and 4 of the rest of the week days.
When I use the formula
cnt:=datediff("d", date(1900,01,01), dt2)/7 - datediff("d", date(1900,01,02), dt1)/7
I show 4.43. Does your formula assume it needs to be rounded up? I tried to run it in my sql plus - but it did not like "DATEDIFF". I ran a modified version (just subtracting the dates) - and it also yielded a fractional number -
1 SELECT
2 (TO_DATE('03/31/2009','MM/DD/YYYY')-TO_DATE('01/01/1900','MM/DD/YYYY'))/7 -
3 (TO_DATE('03/01/2009','MM/DD/YYYY')-TO_DATE('01/01/1900','MM/DD/YYYY'))/7
4 datediff
5* FROM dual
SQL> /
DATEDIFF
----------
4.28571429
SQL>
SQL>
====
Am I missing something. Were the divisions supposed to be truncated maybe?
thanks in advance for your help.
updated - tried with
cnt:=truncate(datediff("d", date(1900,01,01), dt2)/7) -
truncate(datediff("d", date(1900,01,02), dt1)/7)
and intitial testing looks like that may be working (o - i only tested one thing - hopefully this is right....)
Greg
January 15, 2010 at 7:40 am
This might not be the most popular answer: a calendar table is terribly convenient to have around. I made one using the following structure:
CREATE TABLE [dbo].[Calendar](
[dt] [datetime] NOT NULL, --the actual date
[isWeekend] [bit] NOT NULL,
[isHoliday] [bit] NOT NULL,
[day_desc] [nvarchar](50) NULL, --a description for holidays "New Year's Day", "Thanksgiving Day", etc.
[Y] [smallint] NOT NULL, --year
[M] [tinyint] NOT NULL, --month
[D] [tinyint] NOT NULL, --day
[DW] [tinyint] NOT NULL, --day of week [1-7]
[JD] [smallint] NOT NULL, --Julian date [1-366]
[monthname] [varchar](9) NOT NULL,
[dayname] [varchar](9) NOT NULL, --translated day of week "Monday", "Tuesday", etc.
CONSTRAINT [PK_Calendar] PRIMARY KEY CLUSTERED
(
[dt] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I then populated it out 50 years or so. I found a bunch of functions to define the holidays my company observes as well.
Once you have a table like this in place the solution to your challenge (and lots of other challenges) becomes trivial. I consider this the calendar equivalent of my numbers utility table. In fact, I used my numbers table to help me initially populate this calendar table. It makes life easy.
For me, the answer to "How many mondays between two dates?" looks like this:
declare @startdate datetime
declare @enddate datetime
set @startdate = '01/01/2009'
set @enddate = '01/01/2010'
SELECT COUNT(*)
FROM dbo.calendar
WHERE dt >= @startdate
and dt <= @enddate
and DW = 2
May 2, 2019 at 2:41 pm
A different approach is reccursion: (Im using T-sql)
DECLARE @startDate date = '2019-04-01',
@endDate date = '2019-05-01'
;WITH cte AS (
SELECT @startDate as date_
UNION ALL
SELECT CAST(DATEADD(day,1,date_) as date)
FROM cte
WHERE date_ < @endDate
)
SELECT sum(case when datepart(dw,date_) = 2 then 1 else 0 end) as nrOfMondays
FROM cte
Viewing 15 posts - 16 through 30 (of 35 total)
You must be logged in to reply to this topic. Login to reply