এসকিউএল সার্ভারে দুটি তারিখের মধ্যে আমি কীভাবে কাজের দিনগুলি গণনা করতে পারি?
সোমবার থেকে শুক্রবার এবং এটি অবশ্যই টি-এসকিউএল হওয়া উচিত।
এসকিউএল সার্ভারে দুটি তারিখের মধ্যে আমি কীভাবে কাজের দিনগুলি গণনা করতে পারি?
সোমবার থেকে শুক্রবার এবং এটি অবশ্যই টি-এসকিউএল হওয়া উচিত।
উত্তর:
কাজের দিনগুলির জন্য, সোমবার থেকে শুক্রবার পর্যন্ত, আপনি এটির মতো একটি সিলেক্ট করে এটি করতে পারেন:
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = '2008/10/01'
SET @EndDate = '2008/10/31'
SELECT
(DATEDIFF(dd, @StartDate, @EndDate) + 1)
-(DATEDIFF(wk, @StartDate, @EndDate) * 2)
-(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
আপনি যদি ছুটি অন্তর্ভুক্ত করতে চান তবে আপনাকে এটি কিছুটা কাজ করতে হবে ...
-(case datepart(dw, @StartDate)+@@datefirst when 8 then 1 else 0 end) -(case datepart(dw, @EndDate)+@@datefirst when 7 then 1 when 14 then 1 else 0 end)
+(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END) - (CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
ইন গণনা করা হচ্ছে দিন কাজ আপনি এই বিষয় সম্পর্কে একটি ভাল নিবন্ধ খুঁজে পেতে পারেন, কিন্তু আপনি দেখতে পারেন এটা যে উন্নত নয়।
--Changing current database to the Master database allows function to be shared by everyone.
USE MASTER
GO
--If the function already exists, drop it.
IF EXISTS
(
SELECT *
FROM dbo.SYSOBJECTS
WHERE ID = OBJECT_ID(N'[dbo].[fn_WorkDays]')
AND XType IN (N'FN', N'IF', N'TF')
)
DROP FUNCTION [dbo].[fn_WorkDays]
GO
CREATE FUNCTION dbo.fn_WorkDays
--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.
RETURNS INT
AS
--Calculate the RETURN of the function.
BEGIN
--Declare local variables
--Temporarily holds @EndDate during date reversal.
DECLARE @Swap 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
আপনার যদি কাস্টম ক্যালেন্ডার ব্যবহার করতে হয় তবে আপনার কয়েকটি চেক এবং কিছু পরামিতি যুক্ত করতে হতে পারে। আশা করি এটি একটি ভাল সূচনা পয়েন্ট সরবরাহ করবে।
সমস্ত ক্রেডিট বোগদান ম্যাক্সিম এবং পিটার মরটেনসেনকে। এটি তাদের পোস্ট I
--Changing current database to the Master database allows function to be shared by everyone.
USE MASTER
GO
--If the function already exists, drop it.
IF EXISTS
(
SELECT *
FROM dbo.SYSOBJECTS
WHERE ID = OBJECT_ID(N'[dbo].[fn_WorkDays]')
AND XType IN (N'FN', N'IF', N'TF')
)
DROP FUNCTION [dbo].[fn_WorkDays]
GO
CREATE FUNCTION dbo.fn_WorkDays
--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.
RETURNS INT
AS
--Calculate the RETURN of the function.
BEGIN
--Declare local variables
--Temporarily holds @EndDate during date reversal.
DECLARE @Swap 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)
--Subtract all holidays
-(Select Count(*) from [DB04\DB04].[Gateway].[dbo].[tblHolidays]
where [HolDate] between @StartDate and @EndDate )
)
END
GO
-- Test Script
/*
declare @EndDate datetime= dateadd(m,2,getdate())
print @EndDate
select [Master].[dbo].[fn_WorkDays] (getdate(), @EndDate)
*/
WHERE HolDate BETWEEN @StartDate AND @EndDate AND DATEPART(dw, HolDate) BETWEEN 2 AND 6
কেবল সোমবার থেকে শুক্রবার পর্যন্ত ছুটি গণনা করতে।
কার্যদিবসের দিন গণনা করার জন্য অন্য পদ্ধতির একটি হ'ল লুপ ব্যবহার করা যা মূলত একটি তারিখের মধ্য দিয়ে পুনরাবৃত্তি করে এবং যখনই দিনগুলি সোমবার - শুক্রবারের মধ্যে খুঁজে পাওয়া যায় তখন এটি 1 দ্বারা বৃদ্ধি করে। WHILE লুপটি ব্যবহার করে কাজের দিন গণনা করার জন্য সম্পূর্ণ স্ক্রিপ্টটি নীচে দেখানো হয়েছে:
CREATE FUNCTION [dbo].[fn_GetTotalWorkingDaysUsingLoop]
(@DateFrom DATE,
@DateTo DATE
)
RETURNS INT
AS
BEGIN
DECLARE @TotWorkingDays INT= 0;
WHILE @DateFrom <= @DateTo
BEGIN
IF DATENAME(WEEKDAY, @DateFrom) IN('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday')
BEGIN
SET @TotWorkingDays = @TotWorkingDays + 1;
END;
SET @DateFrom = DATEADD(DAY, 1, @DateFrom);
END;
RETURN @TotWorkingDays;
END;
GO
যদিও WHIP লুপ বিকল্পটি ক্লিনার এবং কোডের কম লাইন ব্যবহার করে, এটি আপনার পরিবেশে একটি পারফরম্যান্স বাধা হওয়ার সম্ভাবনা রয়েছে বিশেষত যখন আপনার তারিখের পরিধি বেশ কয়েক বছর ধরে বিস্তৃত হয়।
এই নিবন্ধে কাজের দিন এবং ঘন্টা গণনা করার জন্য আপনি আরও পদ্ধতিগুলি দেখতে পারেন: https://www.sqlshack.com/how-to-calculate-work-days-and-hours-in-sql-server/
ফাংশন হিসাবে স্বীকৃত উত্তরের আমার সংস্করণটি ব্যবহার করে DATEPART
, সুতরাং এর সাথে লাইনে আমাকে স্ট্রিং তুলনা করতে হবে না
DATENAME(dw, @StartDate) = 'Sunday'
যাইহোক, এখানে আমার ব্যবসায়িক তারিখের ফাংশন
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION BDATEDIFF
(
@startdate as DATETIME,
@enddate as DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE @res int
SET @res = (DATEDIFF(dd, @startdate, @enddate) + 1)
-(DATEDIFF(wk, @startdate, @enddate) * 2)
-(CASE WHEN DATEPART(dw, @startdate) = 1 THEN 1 ELSE 0 END)
-(CASE WHEN DATEPART(dw, @enddate) = 7 THEN 1 ELSE 0 END)
RETURN @res
END
GO
DECLARE @TotalDays INT,@WorkDays INT
DECLARE @ReducedDayswithEndDate INT
DECLARE @WeekPart INT
DECLARE @DatePart INT
SET @TotalDays= DATEDIFF(day, @StartDate, @EndDate) +1
SELECT @ReducedDayswithEndDate = CASE DATENAME(weekday, @EndDate)
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
ELSE 0 END
SET @TotalDays=@TotalDays-@ReducedDayswithEndDate
SET @WeekPart=@TotalDays/7;
SET @DatePart=@TotalDays%7;
SET @WorkDays=(@WeekPart*5)+@DatePart
RETURN @WorkDays
(আমি সুবিধাগুলি মন্তব্য করতে কিছুটা লজ্জা করছি)
আপনি যদি সিএমএসের মার্জিত সমাধানটিতে +1 দিন রেখে যাওয়ার সিদ্ধান্ত নেন মনে রাখবেন যে আপনার শুরুর তারিখ এবং শেষের তারিখ যদি একই সপ্তাহান্তে হয় তবে আপনি একটি নেতিবাচক উত্তর পেয়ে যাবেন। অর্থাত, ২০০৮/১০/২০১৮ থেকে ২০০৮/১০/২০১ returns -র রিটার্ন 1
আমার বরং সরলবাদী সমাধান:
select @Result = (..CMS's answer..)
if (@Result < 0)
select @Result = 0
RETURN @Result
.. যা শেষ তারিখের পরে শুরুর তারিখের সাথে সমস্ত ভুল পোস্ট সেট করে । এমন কিছু যা আপনি খুঁজছেন বা নাও পেতে পারেন।
ছুটির দিন সহ তারিখের পার্থক্যের জন্য আমি এই পথে চলেছি:
1) ছুটির সাথে টেবিল:
CREATE TABLE [dbo].[Holiday](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[Date] [datetime] NOT NULL)
2) আমার মতো আমার প্ল্যানিংস টেবিলটি ছিল এবং আমি খালি কলামের ওয়ার্ক_ডিতে পূরণ করতে চাই:
CREATE TABLE [dbo].[Plan_Phase](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Id_Plan] [int] NOT NULL,
[Id_Phase] [int] NOT NULL,
[Start_Date] [datetime] NULL,
[End_Date] [datetime] NULL,
[Work_Days] [int] NULL)
3) সুতরাং "ওয়ার্ক_ডেস" পাওয়ার জন্য আমার কলামটি পরে পূরণ করতে হবে:
SELECT Start_Date, End_Date,
(DATEDIFF(dd, Start_Date, End_Date) + 1)
-(DATEDIFF(wk, Start_Date, End_Date) * 2)
-(SELECT COUNT(*) From Holiday Where Date >= Start_Date AND Date <= End_Date)
-(CASE WHEN DATENAME(dw, Start_Date) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, End_Date) = 'Saturday' THEN 1 ELSE 0 END)
-(CASE WHEN (SELECT COUNT(*) From Holiday Where Start_Date = Date) > 0 THEN 1 ELSE 0 END)
-(CASE WHEN (SELECT COUNT(*) From Holiday Where End_Date = Date) > 0 THEN 1 ELSE 0 END) AS Work_Days
from Plan_Phase
আমি সাহায্য করতে পারে আশা করি।
চিয়ার্স
এখানে এমন একটি সংস্করণ রয়েছে যা ভালভাবে কাজ করে (আমি মনে করি)। হলিডে টেবিলটিতে হলিডে_ডেট কলাম রয়েছে যা আপনার সংস্থা অনুসরণ করে holidays
DECLARE @RAWDAYS INT
SELECT @RAWDAYS = DATEDIFF(day, @StartDate, @EndDate )--+1
-( 2 * DATEDIFF( week, @StartDate, @EndDate ) )
+ CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END
- CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END
SELECT @RAWDAYS - COUNT(*)
FROM HOLIDAY NumberOfBusinessDays
WHERE [Holiday_Date] BETWEEN @StartDate+1 AND @EndDate
আমি জানি এটি একটি পুরানো প্রশ্ন তবে আমার বেশ কয়েকটি আইটেম রয়েছে এবং কাজের সময়গুলি সঠিকভাবে জমা করার জন্য দিনগুলির দরকার পরে কাজ শুরু করার দিন বাদে আমার জন্য একটি সূত্রের প্রয়োজন ছিল।
পুনরাবৃত্ত উত্তরের কোনওটিই আমার পক্ষে কাজ করেনি।
আমি যেমন একটি সংজ্ঞা ব্যবহার
মধ্যরাত থেকে সোমবার, মঙ্গলবার, বুধবার, বৃহস্পতিবার এবং শুক্রবারে কতবার পার হয়ে যায়?
(অন্যরা সোমবারের পরিবর্তে শনিবার থেকে মধ্যরাত গণনা করতে পারেন)
আমি এই সূত্র দিয়ে শেষ
SELECT DATEDIFF(day, @StartDate, @EndDate) /* all midnights passed */
- DATEDIFF(week, @StartDate, @EndDate) /* remove sunday midnights */
- DATEDIFF(week, DATEADD(day, 1, @StartDate), DATEADD(day, 1, @EndDate)) /* remove saturday midnights */
@StartDate
শনিবার বা শুক্রবারের জন্য অ্যাকাউন্টিং ছিল না । এখানে আমার সংস্করণ:DATEDIFF(day, @StartDate, @EndDate) - DATEDIFF(week, @StartDate, @EndDate) - DATEDIFF(week, DATEADD(day, 1, @StartDate), DATEADD(day, 1, @EndDate)) - (CASE WHEN DATEPART(WEEKDAY, @StartDate) IN (1, 7) THEN 1 ELSE 0 END) + 1
এটি কোনও নির্দিষ্ট ভাষা সেটিংয়ের উপর নির্ভরতা ছাড়াই মূলত সিএমএসের উত্তর। এবং যেহেতু আমরা জেনেরিকের জন্য শুটিং করছি, এর অর্থ এটি সমস্ত @@datefirst
সেটিংসেও কাজ করা উচিত ।
datediff(day, <start>, <end>) + 1 - datediff(week, <start>, <end>) * 2
/* if start is a Sunday, adjust by -1 */
+ case when datepart(weekday, <start>) = 8 - @@datefirst then -1 else 0 end
/* if end is a Saturday, adjust by -1 */
+ case when datepart(weekday, <end>) = (13 - @@datefirst) % 7 + 1 then -1 else 0 end
datediff(week, ...)
সর্বদা সপ্তাহের জন্য শনিবার থেকে রবিবার সীমানা ব্যবহার করে, যাতে অভিব্যক্তিটি সংজ্ঞাবহ হয় এবং এটি সংশোধন করার প্রয়োজন হয় না (যতক্ষণ না সপ্তাহের দিনগুলি সম্পর্কে আমাদের সংজ্ঞাটি ধারাবাহিকভাবে সোমবার শুক্রবারের মধ্যে থাকে।) দিবসটির সংখ্যা অনুযায়ী পৃথক হয় না @@datefirst
সেটিং এবং পরিবর্তিত গণনাগুলি কিছু সংখ্যক গাণিতিকের ছোট্ট জটিলতার সাথে এই সংশোধন পরিচালনা করে।
শনিবার / রবিবার জিনিসটির সাথে কাজ করার একটি পরিষ্কার উপায় হ'ল সপ্তাহের মান মূল্য নির্ধারণের আগে তারিখগুলি অনুবাদ করা। স্থানান্তরিত হওয়ার পরে, মানগুলি একটি স্থির (এবং সম্ভবত আরও পরিচিত) নম্বর অনুসারে ফিরে আসবে যা রবিবার ১ থেকে শুরু হয়ে শনিবার with দিয়ে শেষ হবে।
datediff(day, <start>, <end>) + 1 - datediff(week, <start>, <end>) * 2
+ case when datepart(weekday, dateadd(day, @@datefirst, <start>)) = 1 then -1 else 0 end
+ case when datepart(weekday, dateadd(day, @@datefirst, <end>)) = 7 then -1 else 0 end
আমি সমাধানের এই ফর্মটি কমপক্ষে ২০০২ এবং ইটজিক বেন-গান নিবন্ধটি অনুসরণ করেছি। ( https://technet.microsoft.com/en-us/library/aa175781(v=sql.80).aspx ) যদিও এটির পরে এটির জন্য একটি ছোট ত্বক প্রয়োজনdate
ধরণের গাণিতিকের তারিখ মঞ্জুরি দেয় না , এটি অন্যথায় অভিন্ন।
সম্পাদনা: আমি এটিকে আবার যুক্ত করেছিলাম +1
যা কোনওভাবে বন্ধ ছিল left এটিও লক্ষণীয় যে এই পদ্ধতিটি সর্বদা শুরু এবং শেষ দিনগুলি গণনা করে। এটিও ধরে নিয়েছে যে শেষের তারিখটি শুরু হওয়ার তারিখে বা তার পরে।
একটি তারিখ সারণী ব্যবহার:
DECLARE
@StartDate date = '2014-01-01',
@EndDate date = '2014-01-31';
SELECT
COUNT(*) As NumberOfWeekDays
FROM dbo.Calendar
WHERE CalendarDate BETWEEN @StartDate AND @EndDate
AND IsWorkDay = 1;
আপনার যদি তা না থাকে তবে আপনি একটি নম্বর টেবিল ব্যবহার করতে পারেন:
DECLARE
@StartDate datetime = '2014-01-01',
@EndDate datetime = '2014-01-31';
SELECT
SUM(CASE WHEN DATEPART(dw, DATEADD(dd, Number-1, @StartDate)) BETWEEN 2 AND 6 THEN 1 ELSE 0 END) As NumberOfWeekDays
FROM dbo.Numbers
WHERE Number <= DATEDIFF(dd, @StartDate, @EndDate) + 1 -- Number table starts at 1, we want a 0 base
তাদের উভয়ই দ্রুত হওয়া উচিত এবং এটি অস্পষ্টতা / জটিলতা বের করে। প্রথম বিকল্পটি সেরা তবে আপনার কোনও ক্যালেন্ডার টেবিল না থাকলে আপনি সর্বদা একটি সিটিই দিয়ে একটি সংখ্যা সারণী তৈরি করতে পারেন।
DECLARE @StartDate datetime,@EndDate datetime
select @StartDate='3/2/2010', @EndDate='3/7/2010'
DECLARE @TotalDays INT,@WorkDays INT
DECLARE @ReducedDayswithEndDate INT
DECLARE @WeekPart INT
DECLARE @DatePart INT
SET @TotalDays= DATEDIFF(day, @StartDate, @EndDate) +1
SELECT @ReducedDayswithEndDate = CASE DATENAME(weekday, @EndDate)
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
ELSE 0 END
SET @TotalDays=@TotalDays-@ReducedDayswithEndDate
SET @WeekPart=@TotalDays/7;
SET @DatePart=@TotalDays%7;
SET @WorkDays=(@WeekPart*5)+@DatePart
SELECT @WorkDays
CREATE FUNCTION x
(
@StartDate DATETIME,
@EndDate DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE @Teller INT
SET @StartDate = DATEADD(dd,1,@StartDate)
SET @Teller = 0
IF DATEDIFF(dd,@StartDate,@EndDate) <= 0
BEGIN
SET @Teller = 0
END
ELSE
BEGIN
WHILE
DATEDIFF(dd,@StartDate,@EndDate) >= 0
BEGIN
IF DATEPART(dw,@StartDate) < 6
BEGIN
SET @Teller = @Teller + 1
END
SET @StartDate = DATEADD(dd,1,@StartDate)
END
END
RETURN @Teller
END
আমি এখানে বিভিন্ন উদাহরণ নিয়েছি, তবে আমার বিশেষ পরিস্থিতিতে আমাদের সরবরাহের জন্য একটি @ প্রস্তাবিত তারিখ এবং আইটেমটির আসল প্রাপ্তির জন্য একটি @ রিসিটেডডেট রয়েছে। "প্রতিশ্রুত তারিখ" এর আগে যখন কোনও আইটেমটি পাওয়া গেছে তখন আমি ক্যালেন্ডার আদেশের মাধ্যমে তারিখগুলিকে ফাংশনে পাস করার আদেশ না দিলে গণনাগুলি সঠিকভাবে চলছিল না। প্রতিবারের মতো তারিখগুলি পরীক্ষা করতে চাই না, আমার পক্ষে এটি হ্যান্ডেল করার জন্য আমি ফাংশনটি পরিবর্তন করেছি।
Create FUNCTION [dbo].[fnGetBusinessDays]
(
@PromiseDate date,
@ReceivedDate date
)
RETURNS integer
AS
BEGIN
DECLARE @days integer
SELECT @days =
Case when @PromiseDate > @ReceivedDate Then
DATEDIFF(d,@PromiseDate,@ReceivedDate) +
ABS(DATEDIFF(wk,@PromiseDate,@ReceivedDate)) * 2 +
CASE
WHEN DATENAME(dw, @PromiseDate) <> 'Saturday' AND DATENAME(dw, @ReceivedDate) = 'Saturday' THEN 1
WHEN DATENAME(dw, @PromiseDate) = 'Saturday' AND DATENAME(dw, @ReceivedDate) <> 'Saturday' THEN -1
ELSE 0
END +
(Select COUNT(*) FROM CompanyHolidays
WHERE HolidayDate BETWEEN @ReceivedDate AND @PromiseDate
AND DATENAME(dw, HolidayDate) <> 'Saturday' AND DATENAME(dw, HolidayDate) <> 'Sunday')
Else
DATEDIFF(d,@PromiseDate,@ReceivedDate) -
ABS(DATEDIFF(wk,@PromiseDate,@ReceivedDate)) * 2 -
CASE
WHEN DATENAME(dw, @PromiseDate) <> 'Saturday' AND DATENAME(dw, @ReceivedDate) = 'Saturday' THEN 1
WHEN DATENAME(dw, @PromiseDate) = 'Saturday' AND DATENAME(dw, @ReceivedDate) <> 'Saturday' THEN -1
ELSE 0
END -
(Select COUNT(*) FROM CompanyHolidays
WHERE HolidayDate BETWEEN @PromiseDate and @ReceivedDate
AND DATENAME(dw, HolidayDate) <> 'Saturday' AND DATENAME(dw, HolidayDate) <> 'Sunday')
End
RETURN (@days)
END
যদি আপনার নির্দিষ্ট তারিখে কাজের দিন যুক্ত করতে হয়, তবে আপনি নীচে বর্ণিত একটি ক্যালেন্ডার টেবিলের উপর নির্ভর করে একটি ফাংশন তৈরি করতে পারেন:
CREATE TABLE Calendar
(
dt SMALLDATETIME PRIMARY KEY,
IsWorkDay BIT
);
--fill the rows with normal days, weekends and holidays.
create function AddWorkingDays (@initialDate smalldatetime, @numberOfDays int)
returns smalldatetime as
begin
declare @result smalldatetime
set @result =
(
select t.dt from
(
select dt, ROW_NUMBER() over (order by dt) as daysAhead from calendar
where dt > @initialDate
and IsWorkDay = 1
) t
where t.daysAhead = @numberOfDays
)
return @result
end
DATEDIFF এর মতো, আমি শেষের তারিখটিকে অন্তরটির অংশ হিসাবে বিবেচনা করি না। @ স্টার্টডেট এবং @ এন্ডডেটের মধ্যে রবিবারের সংখ্যা (উদাহরণস্বরূপ) এই "প্রাথমিক" সোমবার এবং @ স্টার্টডেটের মধ্যে রবিবারের সংখ্যাটি "প্রাথমিক" সোমবার এবং @ এন্ডডেট বিয়োগের মধ্যবর্তী সংখ্যার সংখ্যা। এটি জানতে পেরে, আমরা নিম্নে ওয়ার্কডেয়ের সংখ্যা গণনা করতে পারি:
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = '2018/01/01'
SET @EndDate = '2019/01/01'
SELECT DATEDIFF(Day, @StartDate, @EndDate) -- Total Days
- (DATEDIFF(Day, 0, @EndDate)/7 - DATEDIFF(Day, 0, @StartDate)/7) -- Sundays
- (DATEDIFF(Day, -1, @EndDate)/7 - DATEDIFF(Day, -1, @StartDate)/7) -- Saturdays
শুভেচ্ছান্তে!
এটি আমার পক্ষে কাজ করছে, আমার দেশে শনিবার এবং রবিবার অ-কার্যদিবসের দিন।
আমার জন্য @ স্টার্টডেট এবং @ শেষ তারিখের সময়টি গুরুত্বপূর্ণ।
CREATE FUNCTION [dbo].[fnGetCountWorkingBusinessDays]
(
@StartDate as DATETIME,
@EndDate as DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE @res int
SET @StartDate = CASE
WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN DATEADD(dd, 2, DATEDIFF(dd, 0, @StartDate))
WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN DATEADD(dd, 1, DATEDIFF(dd, 0, @StartDate))
ELSE @StartDate END
SET @EndDate = CASE
WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN DATEADD(dd, 0, DATEDIFF(dd, 0, @EndDate))
WHEN DATENAME(dw, @EndDate) = 'Sunday' THEN DATEADD(dd, -1, DATEDIFF(dd, 0, @EndDate))
ELSE @EndDate END
SET @res =
(DATEDIFF(hour, @StartDate, @EndDate) / 24)
- (DATEDIFF(wk, @StartDate, @EndDate) * 2)
SET @res = CASE WHEN @res < 0 THEN 0 ELSE @res END
RETURN @res
END
GO
এর মতো ফাংশন তৈরি করুন:
CREATE FUNCTION dbo.fn_WorkDays(@StartDate DATETIME, @EndDate DATETIME= NULL )
RETURNS INT
AS
BEGIN
DECLARE @Days int
SET @Days = 0
IF @EndDate = NULL
SET @EndDate = EOMONTH(@StartDate) --last date of the month
WHILE DATEDIFF(dd,@StartDate,@EndDate) >= 0
BEGIN
IF DATENAME(dw, @StartDate) <> 'Saturday'
and DATENAME(dw, @StartDate) <> 'Sunday'
and Not ((Day(@StartDate) = 1 And Month(@StartDate) = 1)) --New Year's Day.
and Not ((Day(@StartDate) = 4 And Month(@StartDate) = 7)) --Independence Day.
BEGIN
SET @Days = @Days + 1
END
SET @StartDate = DATEADD(dd,1,@StartDate)
END
RETURN @Days
END
আপনি এই ফাংশনটি কল করতে পারেন:
select dbo.fn_WorkDays('1/1/2016', '9/25/2016')
বা পছন্দ করুন:
select dbo.fn_WorkDays(StartDate, EndDate)
from table1
Create Function dbo.DateDiff_WeekDays
(
@StartDate DateTime,
@EndDate DateTime
)
Returns Int
As
Begin
Declare @Result Int = 0
While @StartDate <= @EndDate
Begin
If DateName(DW, @StartDate) not in ('Saturday','Sunday')
Begin
Set @Result = @Result +1
End
Set @StartDate = DateAdd(Day, +1, @StartDate)
End
Return @Result
শেষ
আমি নীচের টিএসকিউএল একটি মোটামুটি মার্জিত সমাধান পেয়েছি (আমার কাছে ফাংশনগুলি চালানোর অনুমতি নেই)। আমি DATEDIFF
উপেক্ষা পেয়েছিDATEFIRST
এবং আমি চেয়েছিলাম সপ্তাহের প্রথম দিনটি সোমবার হোক। আমিও চেয়েছিলাম প্রথম কার্যদিবসের শূন্য নির্ধারণ করা এবং এটি যদি সপ্তাহান্তে পড়ে তবে সোমবার শূন্য হবে। এটি এমন কাউকে সাহায্য করতে পারে যার সামান্য আলাদা প্রয়োজন আছে :)
এটি ব্যাঙ্কের ছুটি পরিচালনা করে না
SET DATEFIRST 1
SELECT
,(DATEDIFF(DD, [StartDate], [EndDate]))
-(DATEDIFF(wk, [StartDate], [EndDate]))
-(DATEDIFF(wk, DATEADD(dd,-@@DATEFIRST,[StartDate]), DATEADD(dd,-@@DATEFIRST,[EndDate]))) AS [WorkingDays]
FROM /*Your Table*/
একটি পদ্ধতি হ'ল 'তারিখগুলি হাঁটা' একটি কেস এক্সপ্রেশনের সাথে শুরু করে যা দিনটি শনিবার বা রবিবার না হয় এবং এটি পতাকাঙ্কিত করে কিনা তা পরীক্ষা করে দেখায় (সপ্তাহের দিনের জন্য 1, সাপ্তাহিক ছুটির জন্য 0)। এবং শেষ পর্যন্ত সপ্তাহের দিনগুলির সংখ্যা দেওয়ার জন্য কেবল পতাকাগুলি সমষ্টি (এটি অন্যান্য পতাকা হিসাবে 0-এর পতাকা হিসাবে গণনার সমান হবে)।
আপনি একটি getNums (startNumber, endNumber) প্রকারের ইউটিলিটি ফাংশন ব্যবহার করতে পারেন যা 'লুপিং' এর জন্য শুরুর তারিখ থেকে শেষের তারিখ পর্যন্ত একটি ধারাবাহিক সংখ্যা তৈরি করে। পড়ুন http://tsql.solidq.com/SourceCodes/GetNums.txt একটি বাস্তবায়ন জন্য। যুক্তিটিও ছুটির দিনগুলি পূরণ করতে বাড়ানো যেতে পারে (বলুন যে আপনার যদি ছুটির টেবিল থাকে)
declare @date1 as datetime = '19900101'
declare @date2 as datetime = '19900120'
select sum(case when DATENAME(DW,currentDate) not in ('Saturday', 'Sunday') then 1 else 0 end) as noOfWorkDays
from dbo.GetNums(0,DATEDIFF(day,@date1, @date2)-1) as Num
cross apply (select DATEADD(day,n,@date1)) as Dates(currentDate)
আমার সমাধান তৈরির জন্য আমি অন্যের কাছ থেকে কিছু ধারণা ধার নিয়েছি। আমি সাপ্তাহিক ছুটির দিন এবং মার্কিন যুক্তরাষ্ট্রীয় ছুটির দিনগুলি উপেক্ষা করতে ইনলাইন কোড ব্যবহার করি। আমার পরিবেশে, এন্ডডেটটি শূন্য হতে পারে তবে এটি কখনও স্টার্টেটের আগে চলে না।
CREATE FUNCTION dbo.ufn_CalculateBusinessDays(
@StartDate DATE,
@EndDate DATE = NULL)
RETURNS INT
AS
BEGIN
DECLARE @TotalBusinessDays INT = 0;
DECLARE @TestDate DATE = @StartDate;
IF @EndDate IS NULL
RETURN NULL;
WHILE @TestDate < @EndDate
BEGIN
DECLARE @Month INT = DATEPART(MM, @TestDate);
DECLARE @Day INT = DATEPART(DD, @TestDate);
DECLARE @DayOfWeek INT = DATEPART(WEEKDAY, @TestDate) - 1; --Monday = 1, Tuesday = 2, etc.
DECLARE @DayOccurrence INT = (@Day - 1) / 7 + 1; --Nth day of month (3rd Monday, for example)
--Increment business day counter if not a weekend or holiday
SELECT @TotalBusinessDays += (
SELECT CASE
--Saturday OR Sunday
WHEN @DayOfWeek IN (6,7) THEN 0
--New Year's Day
WHEN @Month = 1 AND @Day = 1 THEN 0
--MLK Jr. Day
WHEN @Month = 1 AND @DayOfWeek = 1 AND @DayOccurrence = 3 THEN 0
--G. Washington's Birthday
WHEN @Month = 2 AND @DayOfWeek = 1 AND @DayOccurrence = 3 THEN 0
--Memorial Day
WHEN @Month = 5 AND @DayOfWeek = 1 AND @Day BETWEEN 25 AND 31 THEN 0
--Independence Day
WHEN @Month = 7 AND @Day = 4 THEN 0
--Labor Day
WHEN @Month = 9 AND @DayOfWeek = 1 AND @DayOccurrence = 1 THEN 0
--Columbus Day
WHEN @Month = 10 AND @DayOfWeek = 1 AND @DayOccurrence = 2 THEN 0
--Veterans Day
WHEN @Month = 11 AND @Day = 11 THEN 0
--Thanksgiving
WHEN @Month = 11 AND @DayOfWeek = 4 AND @DayOccurrence = 4 THEN 0
--Christmas
WHEN @Month = 12 AND @Day = 25 THEN 0
ELSE 1
END AS Result);
SET @TestDate = DATEADD(dd, 1, @TestDate);
END
RETURN @TotalBusinessDays;
END