September 10, 2007 at 5:37 pm
Cool Kurt... wanna share your SQL code on this?
--Jeff Moden
Change is inevitable... Change for the better is not.
September 10, 2007 at 6:25 pm
Hi Jeff,
Yes, your algorithm is indeed correct. I never really doubted that ... I always suspected it was a db data issue.
With help from Sergiy the date conversion allowed me to spot that the dates were 2 days out in the SQL db compared to how they were entered in the App. Hence, why it gave 21 days ... the App dates of 1st May - 31st May should have given 23 weekdays, but because the App was then saving them in the SQL server with a 2-day offset the SQL server actually had them as 3rd May to 2nd June which is indeed 21 weekdays.
Thanks
September 10, 2007 at 9:29 pm
Ah... got it... had to go back and look... Serqiy is correct and I'll throw in that you may not ever want to pass date serial numbers between products... Best bet is probably ISO dates. I believe that Excel has even a different day zero than VB or SQL Server.
Sorry I didn't get what you were saying the first time.
--Jeff Moden
Change is inevitable... Change for the better is not.
October 24, 2007 at 10:33 pm
There is scope for another function work hours in a daterange
regards
john
October 24, 2007 at 10:35 pm
Excellent observation!
--Jeff Moden
Change is inevitable... Change for the better is not.
December 26, 2007 at 9:36 am
sorry folks,
I am a newbie here and I wonder if some one is kind enough and explain to me how do I get the number of days out of this SP or how do I run this SP in Query Analyzer and see the result there. I tried to run this SP and nothing come back.
December 26, 2007 at 9:55 am
Post the code that you tried, Tony... it's the only way we can see what might be wrong...
--Jeff Moden
Change is inevitable... Change for the better is not.
December 26, 2007 at 10:15 am
Hi,
Jeff I try to understand your code and learn how to work with SP and all. Here is what I tried to run the example that you wrote here (finding number of workdays)
http://www.sqlservercentral.com/articles/Advanced+Querying/calculatingworkdays/1660/
--query analyzer----
Declare @startdate datetime, @enddate datetime
Select @startdate = '12/17/2007', @enddate = '12/25/2007'
Exec dbo.fn_WorkDays @startdate, @enddate
---coldfusion----
I am not sure if I have the CF call right either..Can you show me the way. Thanks
December 26, 2007 at 10:17 am
How do I post CF code here??
December 26, 2007 at 10:28 am
First, dunno how to post CF code on this forum mostly because I've never used CF.
Still need to see code... I see that you've created a function to use the "method", and I need to see that to help you figure out why you're not getting a return.
--Jeff Moden
Change is inevitable... Change for the better is not.
December 26, 2007 at 10:54 am
The only thing I changed was to make it as SP instead of a function. Thanks
---Declare @startdate datetime, @enddate datetime
---Select @startdate = '12/17/2007', @enddate = '12/25/2007'
Exec dbo.TEST_WorkDays '12/17/2007', '12/25/2007'
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE procedure dbo.TEST_WorkDays
/***************************************************************************************
Purpose:
1. Given any valid start date and end date, this function will calculate and return
the number of workdays (Mon - Fri).
2. Given only a valid start date (end date has DEFAULT in it), this function will
return a 1 if the start date is a weekday and a 0 if not a weekday.
Usage:
1. MASTER.dbo.TEST_WorkDays(@StartDate,@EndDate)
2. MASTER.dbo.TEST_WorkDays(@StartDate,DEFAULT) --Always returns 1 or 0
3. MASTER.dbo.TEST_WorkDays(@EndDate,@StartDate)
4. MASTER.dbo.TEST_WorkDays(@StartDate,@StartDate) --Always returns 1 or 0
5. MASTER.dbo.TEST_WorkDays(@EndDate,@EndDate) --Always returns 1 or 0
Notes:
1. Holidays are NOT considered.
2. Because of the way SQL Server calculates weeks and named days of the week, no
special consideration for the value of DATEFIRST is given. In other words, it
doesn't matter what DATEFIRST is set to for this function.
3. If the input dates are in the incorrect order, they will be reversed prior to any
calculations.
4. Only whole days are considered. Times are NOT used.
5. The number of workdays INCLUDES both dates
6. Inputs may be literal representations of dates, datetime datatypes, numbers that
represent the number of days since 1/1/1900 00:00:00.000, or anything else that can
be implicitly converted to or already is a datetime datatype.
7. Undocumented: The DATEPART(dw,date) does not actually count weeks... It counts the
transition to a Sunday regardless of the DATEFIRST setting. In essence, it counts
only whole weekends in any given date range.
8. This UDF does NOT create a tally table or sequence table to operate. Not only is
it set based, it is truly "tableless".
Error Indications:
1. If either the @StartDate or the @EndDate parameter is an invalid date, the
following error is returned...
"Server: Msg 242, Level 16, State 3, Line 3
The conversion of a char data type to a datetime data type resulted in an
out-of-range datetime value."
2. If either the @StartDate or the @EndDate parameter is a string not resembling a
date, the following error is returned...
"Server: Msg 241, Level 16, State 1, Line 3
Syntax error converting datetime from character string."
3. If only one parameter is passed, the following error is returned...
"Server: Msg 313, Level 16, State 2, Line 3
An insufficient number of arguments were supplied for the procedure or
function MASTER.dbo.fn_WorkDays."
Return NULL if @StartDate is NULL or DEFAULT and
modify to be insensitive to DATEFIRST settings.
***************************************************************************************/
--======================================================================================
-- Presets
--======================================================================================
--===== Define the input parameters (ok if reversed by mistake)
(
@StartDate DATETIME,
@EndDate DATETIME = NULL --@EndDate replaced by @StartDate when DEFAULTed
)
--===== Define the output data type
RETURN INT
AS
--======================================================================================
-- Calculate the RETURN of the function
--======================================================================================
BEGIN
--===== Declare local variables
--Temporarily holds @EndDate during date reversal
DECLARE @Swap DATETIME, @Days DATETIME
--===== If the Start Date is null, return a NULL and exit
IF @StartDate IS NULL
RETURN NULL
--===== If the End Date is null, populate with Start Date value
-- so will have two dates (required by DATEDIFF below)
IF @EndDate IS NULL
SELECT @EndDate = @StartDate
--===== Strip the time element from both dates (just to be safe) by converting
-- to whole days and back to a date. Usually faster than CONVERT.
-- 0 is a date (01/01/1900 00:00:00.000)
SELECT @StartDate = DATEADD(dd,DATEDIFF(dd,0,@StartDate),0),
@EndDate = DATEADD(dd,DATEDIFF(dd,0,@EndDate) ,0)
--===== If the inputs are in the wrong order, reverse them
IF @StartDate > @EndDate
SELECT @Swap = @EndDate,
@EndDate = @StartDate,
@StartDate = @Swap
--===== Calculate and return the number of workdays using the
-- input parameters. This is the meat of the function.
-- This is really just one formula with a couple of parts
-- that are listed on separate lines for documentation
-- purposes.
RETURN (
SELECT
--Start with total number of days including weekends
(DATEDIFF(dd,@StartDate,@EndDate)+1)
--Subtact 2 days for each full weekend
-(DATEDIFF(wk,@StartDate,@EndDate)*2)
--If StartDate is a Sunday, Subtract 1
-(CASE WHEN DATENAME(dw,@StartDate) = 'Sunday'
THEN 1
ELSE 0
END)
--If EndDate is a Saturday, Subtract 1
-(CASE WHEN DATENAME(dw,@EndDate) = 'Saturday'
THEN 1
ELSE 0
END)
)
END
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
December 26, 2007 at 12:33 pm
Heh... If you're going to copy code 100%, the least you could do is put my name on it 😉
First, why are you using this as a proc... why not just use it as a function? That would be perfect...
Second, if you have a DBA that would rather have scalar procs instead of the benefit of scalar functions, then you need to add another variable to the proc and the call.
--======================================================================================
-- Presets
--======================================================================================
--===== Define the input parameters (ok if reversed by mistake)
(
@StartDate DATETIME,
@EndDate DATETIME = NULL, --@EndDate replaced by @StartDate when DEFAULTed
@WorkDays INT OUTPUT
)
----===== Define the output data type
--RETURN INT
AS
--======================================================================================
-- Calculate the RETURN of the function
--======================================================================================
BEGIN
--===== Declare local variables
--Temporarily holds @EndDate during date reversal
DECLARE @Swap DATETIME, @Days DATETIME
--===== If the Start Date is null, return a NULL and exit
IF @StartDate IS NULL
BEGIN
SELECT @WordDays = NULL
RETURN
END
--===== If the End Date is null, populate with Start Date value
-- so will have two dates (required by DATEDIFF below)
IF @EndDate IS NULL
SELECT @EndDate = @StartDate
--===== Strip the time element from both dates (just to be safe) by converting
-- to whole days and back to a date. Usually faster than CONVERT.
-- 0 is a date (01/01/1900 00:00:00.000)
SELECT @StartDate = DATEADD(dd,DATEDIFF(dd,0,@StartDate),0),
@EndDate = DATEADD(dd,DATEDIFF(dd,0,@EndDate) ,0)
--===== If the inputs are in the wrong order, reverse them
IF @StartDate > @EndDate
SELECT @Swap = @EndDate,
@EndDate = @StartDate,
@StartDate = @Swap
--===== Calculate and return the number of workdays using the
-- input parameters. This is the meat of the function.
-- This is really just one formula with a couple of parts
-- that are listed on separate lines for documentation
-- purposes.
--RETURN (
SELECT @WorkDays =
--Start with total number of days including weekends
(DATEDIFF(dd,@StartDate,@EndDate)+1)
--Subtact 2 days for each full weekend
-(DATEDIFF(wk,@StartDate,@EndDate)*2)
--If StartDate is a Sunday, Subtract 1
-(CASE WHEN DATENAME(dw,@StartDate) = 'Sunday'
THEN 1
ELSE 0
END)
--If EndDate is a Saturday, Subtract 1
-(CASE WHEN DATENAME(dw,@EndDate) = 'Saturday'
THEN 1
ELSE 0
END)
--)
And, the call should be...
Declare @startdate datetime, @enddate datetime, @WorkDays INT
Select @startdate = '12/17/2007', @enddate = '12/25/2007'
Exec dbo.TEST_WorkDays @startdate , @enddate , @WorkDays OUTPUT
Note that some of the code in the red areas above have simply been commented out and don't actually need to be included in the code.
Function would still be better. Also, since you're new, you may want to study "CREATE PROCEDURE" in Books OnLine for how to return data through variables in a proc like this.
--Jeff Moden
Change is inevitable... Change for the better is not.
December 26, 2007 at 12:47 pm
thanks Jeff,
I am still learning and this is just to see how it works. Sure if I use the code anywhere, your name will be there.
I am not so familiar with function ( I had a little more on sp) that's why. On top of that I am using CF, I have not yet get to the point of calling a function as I am learning the rope on proc & CF.I will give it another try and thanks for being patient with me.
Tony
December 26, 2007 at 1:17 pm
ahhh.... error....."has too many arguments specified"
Declare @StartDate datetime, @EndDate datetime, @WorkDays INT
Select @StartDate = '12/17/2007', @EndDate = '12/25/2007'
Exec dbo.PIN_WorkDays @StartDate, @EndDate, @WorkDays OUTPUT
using exactly what previously corrected (except for 'worddays'...spelling??)
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
ALTER procedure dbo.PIN_WorkDays
Return NULL if @StartDate is NULL or DEFAULT and
modify to be insensitive to DATEFIRST settings.
***************************************************************************************/
--======================================================================================
-- Presets
--======================================================================================
--===== Define the input parameters (ok if reversed by mistake)
(
@StartDate DATETIME,
@EndDate DATETIME = NULL, --@EndDate replaced by @StartDate when DEFAULTed
@WorkDays INT OUTPUT
)
--===== Define the output data type
RETURN INT
AS
--======================================================================================
-- Calculate the RETURN of the function
--======================================================================================
BEGIN
--===== Declare local variables
--Temporarily holds @EndDate during date reversal
DECLARE @Swap DATETIME, @Days DATETIME
IF @StartDate IS NULL
BEGIN
SELECT @WorkDays = NULL
RETURN
END
--===== If the Start Date is null, return a NULL and exit
IF @StartDate IS NULL
RETURN NULL
--===== If the End Date is null, populate with Start Date value
-- so will have two dates (required by DATEDIFF below)
IF @EndDate IS NULL
SELECT @EndDate = @StartDate
--===== Strip the time element from both dates (just to be safe) by converting
-- to whole days and back to a date. Usually faster than CONVERT.
-- 0 is a date (01/01/1900 00:00:00.000)
SELECT @StartDate = DATEADD(dd,DATEDIFF(dd,0,@StartDate),0),
@EndDate = DATEADD(dd,DATEDIFF(dd,0,@EndDate) ,0)
--===== If the inputs are in the wrong order, reverse them
IF @StartDate > @EndDate
SELECT @Swap = @EndDate,
@EndDate = @StartDate,
@StartDate = @Swap
--===== Calculate and return the number of workdays using the
-- input parameters. This is the meat of the function.
-- This is really just one formula with a couple of parts
-- that are listed on separate lines for documentation
-- purposes.
--RETURN (
SELECT @WorkDays =
--Start with total number of days including weekends
(DATEDIFF(dd,@StartDate,@EndDate)+1)
--Subtact 2 days for each full weekend
-(DATEDIFF(wk,@StartDate,@EndDate)*2)
--If StartDate is a Sunday, Subtract 1
-(CASE WHEN DATENAME(dw,@StartDate) = 'Sunday'
THEN 1
ELSE 0
END)
--If EndDate is a Saturday, Subtract 1
-(CASE WHEN DATENAME(dw,@EndDate) = 'Saturday'
THEN 1
ELSE 0
END)
--)
END
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
December 26, 2007 at 4:16 pm
I haven't check all the code, but I see that you have a RETURN that I commented out in red...
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 15 posts - 76 through 90 (of 156 total)
You must be logged in to reply to this topic. Login to reply