দুটি তারিখের মধ্যে কাজের দিন গণনা করুন


163

এসকিউএল সার্ভারে দুটি তারিখের মধ্যে আমি কীভাবে কাজের দিনগুলি গণনা করতে পারি?

সোমবার থেকে শুক্রবার এবং এটি অবশ্যই টি-এসকিউএল হওয়া উচিত।


5
আপনি কাজের দিন সংজ্ঞায়িত করতে পারেন? শুক্রবারের মধ্যে কোন সোমবার? প্রধান ছুটি বাদে? কোন দেশ? এটি এসকিউএল এ করা উচিত?
ডেভ কে

উত্তর:


301

কাজের দিনগুলির জন্য, সোমবার থেকে শুক্রবার পর্যন্ত, আপনি এটির মতো একটি সিলেক্ট করে এটি করতে পারেন:

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)

আপনি যদি ছুটি অন্তর্ভুক্ত করতে চান তবে আপনাকে এটি কিছুটা কাজ করতে হবে ...


3
আমি ঠিক বুঝতে পেরেছি যে এই কোডটি সর্বদা কার্যকর হয় না! আমি চেষ্টা এই: সেট @StartDate = '28 -mar-2011 'সেট @EndDate = '29 -mar-2011' উত্তর এটি 2 দিন যেমন গণনা করা হয়েছে
greektreat

16
@ গ্রিকট্রেট এটি দুর্দান্ত কাজ করে। এটি ঠিক যে @ স্টার্টডেট এবং @ এন্ডডেট উভয়ই গণনায় অন্তর্ভুক্ত। আপনি যদি সোমবার থেকে মঙ্গলবার 1 দিন হিসাবে গণনা করতে চান তবে প্রথম ডেটেডিএফের পরে কেবল "+ 1" সরান। তারপরে আপনি শুক্র-> শনি = 0, শুক্র-> সান = 0, শুক্র-> সোম = 1 পাবেন।
জো ডেলি

6
@ জোড্যালিকে অনুসরণ করে শুরুর তারিখ গণনা থেকে বাদ দেওয়ার জন্য আপনি যখন DATEDIFF এর পরে +1 সরিয়ে ফেলেন তখন আপনাকে এর CASE অংশটিও সামঞ্জস্য করতে হবে। আমি এটি ব্যবহার করে শেষ করেছি: + (CASE WHEN DATENAME (dw, @StartDate) = 'শনিবার' তৃতীয় 1 ইলেএসই 0 শেষ) - (কেসেন WHEN তারিখের নাম (ডাব্লু, @ শেষ তারিখ) = 'শনিবার' তত 1 ই
এলএসই

7
তারিখের নামটি ফাংশনটি লোকাল-নির্ভর। আরও শক্তিশালী তবে আরও অস্পষ্ট সমাধান হ'ল শেষ দুটি লাইনটি প্রতিস্থাপন করুন:-(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)
টরবেন ক্লেইন

2
@ সিকেনজিয়ার মন্তব্য স্পষ্ট করতে আপনি রবিবার সম্পর্কে মামলার বক্তব্য পুরোপুরি সরিয়ে ফেলবেন, কেবল রেখেই যাবেন+(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END) - (CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
অ্যান্ডি রাদ্দাটজ

32

ইন গণনা করা হচ্ছে দিন কাজ আপনি এই বিষয় সম্পর্কে একটি ভাল নিবন্ধ খুঁজে পেতে পারেন, কিন্তু আপনি দেখতে পারেন এটা যে উন্নত নয়।

--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

আপনার যদি কাস্টম ক্যালেন্ডার ব্যবহার করতে হয় তবে আপনার কয়েকটি চেক এবং কিছু পরামিতি যুক্ত করতে হতে পারে। আশা করি এটি একটি ভাল সূচনা পয়েন্ট সরবরাহ করবে।


এটি কীভাবে কাজ করে তা বোঝার জন্য লিঙ্কটি অন্তর্ভুক্ত করার জন্য ধন্যবাদ। স্কেলসার্ভারসেন্ট্রালে লেখাটি দুর্দান্ত ছিল!
ক্রিস পোর্টার

20

সমস্ত ক্রেডিট বোগদান ম্যাক্সিম এবং পিটার মরটেনসেনকে। এটি তাদের পোস্ট 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)
*/

2
হাই ড্যান বি মাত্র আপনাকে জানাতে যে আপনার সংস্করণটি ধরে নিয়েছে যে টেবিল টিবিএলহ্যালিডে শনি ও সোমবার থাকে না, যা কখনও কখনও ঘটে থাকে। যাইহোক, আপনার সংস্করণ ভাগ করে নেওয়ার জন্য ধন্যবাদ। চিয়ার্স
জুলিও নোব্রে

3
জুলিও - হ্যাঁ - আমার সংস্করণটি ধরে নিয়েছে যে শনিবার এবং রবিবার (সোমবারের নয়) সপ্তাহান্তে, এবং এর জন্য "অ-ব্যবসায়িক" দিন নয়। তবে আপনি যদি সপ্তাহান্তে কাজ করছেন, তবে আমার অনুমান হয় যে প্রতিদিন একটি "ওয়ার্ক ডে" এবং আপনি এই ধারাটির শনি ও রবিবার অংশটি মন্তব্য করতে পারেন এবং আপনার সমস্ত ছুটির দিনগুলিতে টিবিএল হলিডে টেবিলের সাথে যুক্ত করতে পারেন।
ড্যান বি

1
ধন্যবাদ ড্যান আমি আমার ফাংশন এই অন্তর্ভূক্ত টেবিলের সকল তারিখ, ছুটির দিন, ইত্যাদি আপনার ফাংশন গ্রহণ অন্তর্ভুক্ত আমার DateDimensions যেমন ছুটির জন্য একটি চেক যোগ, আমি শুধু যোগ করেছেন: এবং IsWeekend = 0 পর যেখানে [HolDate] StartDate এবং EndDate) মধ্যে
AlsoKnownAsJazz

যদি হলিডে টেবিলটিতে উইকএন্ডে ছুটি থাকে, আপনি এই জাতীয় মানদণ্ডগুলি সংশোধন করতে পারেন: WHERE HolDate BETWEEN @StartDate AND @EndDate AND DATEPART(dw, HolDate) BETWEEN 2 AND 6কেবল সোমবার থেকে শুক্রবার পর্যন্ত ছুটি গণনা করতে।
আন্দ্রে

7

কার্যদিবসের দিন গণনা করার জন্য অন্য পদ্ধতির একটি হ'ল লুপ ব্যবহার করা যা মূলত একটি তারিখের মধ্য দিয়ে পুনরাবৃত্তি করে এবং যখনই দিনগুলি সোমবার - শুক্রবারের মধ্যে খুঁজে পাওয়া যায় তখন এটি 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/


6

ফাংশন হিসাবে স্বীকৃত উত্তরের আমার সংস্করণটি ব্যবহার করে 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

5
 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

আপনি যদি কোড, এক্সএমএল বা ডেটা নমুনাগুলি পোস্ট করেন তবে দয়া করে টেক্সট সম্পাদকের সেই লাইনগুলি হাইলাইট করুন এবং এটিকে হাইলাইট করার জন্য সম্পাদক সরঞ্জামদণ্ডে "কোড স্যাম্পল" বোতামটি ({}) ক্লিক করুন!
marc_s

দুর্দান্ত, এটি ব্যবহার করে পেরিফেরি ফাংশন বা ডেটাবেসের আপডেটের প্রয়োজন নেই। ধন্যবাদ। বিটিডব্লিউ :
ব্রায়ান স্কট

সুপার সমাধান। আমি যেমন 2 টি টেবিল কলামে তারিখগুলির মধ্যে সপ্তাহের দিনগুলি (এমএফ) গণনা করার জন্য একটি ওয়েব ইউনিভার্সে ভেরিয়েবলগুলি ব্যবহারের জন্য সূত্রগুলিতে সাবস্ক্রাইব করেছি ... (((DATEDIFF (দিন, টেবিল কোড 1, টেবিল কোড 2) +1) - ((কেস ডেটনেম (সপ্তাহের দিন, টেবিল কোড ২2) যখন 'শনিবার' তখন 1 তম 1 'রবিবার' তৃতীয় 2 তম ইলিশ 0 সমাপ্তি))) / 7) * 5) + ((ডেটেডিএফ (দিন, টেবিল কোড 1, টেবিল কোড 2 ) +1) - ((কেস ডেটনেম (সপ্তাহের দিন, টেবিল কোড ২2) যখন 'শনিবার' তখন 1 তম 1 'রবিবার' তখন 2 ই এলএসই 0 সমাপ্তি)))% 7)
হিলারি

5

(আমি সুবিধাগুলি মন্তব্য করতে কিছুটা লজ্জা করছি)

আপনি যদি সিএমএসের মার্জিত সমাধানটিতে +1 দিন রেখে যাওয়ার সিদ্ধান্ত নেন মনে রাখবেন যে আপনার শুরুর তারিখ এবং শেষের তারিখ যদি একই সপ্তাহান্তে হয় তবে আপনি একটি নেতিবাচক উত্তর পেয়ে যাবেন। অর্থাত, ২০০৮/১০/২০১৮ থেকে ২০০৮/১০/২০১ returns -র রিটার্ন 1

আমার বরং সরলবাদী সমাধান:

select @Result = (..CMS's answer..)
if  (@Result < 0)
        select @Result = 0
    RETURN @Result

.. যা শেষ তারিখের পরে শুরুর তারিখের সাথে সমস্ত ভুল পোস্ট সেট করে । এমন কিছু যা আপনি খুঁজছেন বা নাও পেতে পারেন।


5

ছুটির দিন সহ তারিখের পার্থক্যের জন্য আমি এই পথে চলেছি:

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

আমি সাহায্য করতে পারে আশা করি।

চিয়ার্স


1
আপনার ছুটির বিয়োগগুলি সম্পর্কিত। শুরু করার তারিখ 1 জানুয়ারী এবং শেষ তারিখ 31 ডিসেম্বর হলে কী হবে? আপনি কেবল 2 বিয়োগ করবেন - যা ভুল। আমি DATEDIFF (দিন, শুরু_ তারিখ, তারিখ) এবং সম্পূর্ণ 'হলিডে থেকে নির্বাচন করুন' (*) এর পরিবর্তে এন্ড_ডেটের জন্য একই ব্যবহার করার প্রস্তাব করছি।
ইলিয়া রাতক্যাভিচ

4

এখানে এমন একটি সংস্করণ রয়েছে যা ভালভাবে কাজ করে (আমি মনে করি)। হলিডে টেবিলটিতে হলিডে_ডেট কলাম রয়েছে যা আপনার সংস্থা অনুসরণ করে 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 

এই ছুটির তারিখগুলিও সাপ্তাহিক ছুটিতে পড়তে পারে। এবং কারও কারও জন্য, রবিবারের ছুটি পরবর্তী সোমবার দ্বারা প্রতিস্থাপন করা হবে।
ইরান সোতোমো

3

আমি জানি এটি একটি পুরানো প্রশ্ন তবে আমার বেশ কয়েকটি আইটেম রয়েছে এবং কাজের সময়গুলি সঠিকভাবে জমা করার জন্য দিনগুলির দরকার পরে কাজ শুরু করার দিন বাদে আমার জন্য একটি সূত্রের প্রয়োজন ছিল।

পুনরাবৃত্ত উত্তরের কোনওটিই আমার পক্ষে কাজ করেনি।

আমি যেমন একটি সংজ্ঞা ব্যবহার

মধ্যরাত থেকে সোমবার, মঙ্গলবার, বুধবার, বৃহস্পতিবার এবং শুক্রবারে কতবার পার হয়ে যায়?

(অন্যরা সোমবারের পরিবর্তে শনিবার থেকে মধ্যরাত গণনা করতে পারেন)

আমি এই সূত্র দিয়ে শেষ

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 */

1
সে আমার জন্য এটি করেছে তবে আমাকে একটি ছোট পরিবর্তন করতে হয়েছিল। এটি কখন @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
caiosm1005

@ caiosm1005, শনিবার রবিবার 0, শনিবার সোমবার ফেরত 1, শুক্রবার শনিবারের রিটার্ন 0 সবই আমার সংজ্ঞার সাথে সামঞ্জস্যপূর্ণ। আপনার কোডটি সঠিকভাবে জমা হবে না (যেমন শুক্রবার শুক্রবারে 6
টা ফিরবেন

3

এটি কোনও নির্দিষ্ট ভাষা সেটিংয়ের উপর নির্ভরতা ছাড়াই মূলত সিএমএসের উত্তর। এবং যেহেতু আমরা জেনেরিকের জন্য শুটিং করছি, এর অর্থ এটি সমস্ত @@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 এটিও লক্ষণীয় যে এই পদ্ধতিটি সর্বদা শুরু এবং শেষ দিনগুলি গণনা করে। এটিও ধরে নিয়েছে যে শেষের তারিখটি শুরু হওয়ার তারিখে বা তার পরে।


দ্রষ্টব্য যে এটি সাপ্তাহিক অনেকগুলি তারিখের জন্য ভুল ফলাফলগুলি ফিরিয়ে দেবে যাতে তারা আপ্প যোগ না করে (শুক্র-> সোমটি শুক্র-> শনি + শনি-> সান + রবি> সোমবারের মতো হওয়া উচিত)। শুক্র-> শনিটি 0 (সঠিক) হওয়া উচিত, শনি-> সূর্যের পরিমাণ 0 (ভুল -1) হওয়া উচিত, সূর্য-> সোম সোম 1 (ভুল 0) হওয়া উচিত। এটি থেকে অনুসরণ করা অন্যান্য ত্রুটিগুলি হ'ল Sat-> শনি = -1, সূর-> সান = -1, সূর্য-> শনি = 4
অ্যাড্রিনিম

@ অ্যাড্রিয়ানম আমি বিশ্বাস করি যে আমি সমস্যাগুলি সংশোধন করেছি। আসলে সমস্যাটি হ'ল এটি সর্বদা একসময় বন্ধ ছিল কারণ আমি দুর্ভাগ্যক্রমে dropped অংশটি একরকম ফেলে দিয়েছিলাম।
shawnt00

আপডেটের জন্য ধন্যবাদ. আমি ভেবেছিলাম আপনার সূত্রটি শুরুর তারিখ বাদ দিচ্ছে যা আমার প্রয়োজন। এটি নিজেই সমাধান করেছেন এবং এটিকে অন্য উত্তর হিসাবে যুক্ত করেছেন।
অ্যাড্রিনিম

2

একটি তারিখ সারণী ব্যবহার:

    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

তাদের উভয়ই দ্রুত হওয়া উচিত এবং এটি অস্পষ্টতা / জটিলতা বের করে। প্রথম বিকল্পটি সেরা তবে আপনার কোনও ক্যালেন্ডার টেবিল না থাকলে আপনি সর্বদা একটি সিটিই দিয়ে একটি সংখ্যা সারণী তৈরি করতে পারেন।


1
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

আপনি যদি কোনও ফাংশন ব্যবহার করতে যাচ্ছেন তবে মারিও মাইরেলিসের উত্তরের
জেমস জেনকিনস

1
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

1

আমি এখানে বিভিন্ন উদাহরণ নিয়েছি, তবে আমার বিশেষ পরিস্থিতিতে আমাদের সরবরাহের জন্য একটি @ প্রস্তাবিত তারিখ এবং আইটেমটির আসল প্রাপ্তির জন্য একটি @ রিসিটেডডেট রয়েছে। "প্রতিশ্রুত তারিখ" এর আগে যখন কোনও আইটেমটি পাওয়া গেছে তখন আমি ক্যালেন্ডার আদেশের মাধ্যমে তারিখগুলিকে ফাংশনে পাস করার আদেশ না দিলে গণনাগুলি সঠিকভাবে চলছিল না। প্রতিবারের মতো তারিখগুলি পরীক্ষা করতে চাই না, আমার পক্ষে এটি হ্যান্ডেল করার জন্য আমি ফাংশনটি পরিবর্তন করেছি।

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

1

যদি আপনার নির্দিষ্ট তারিখে কাজের দিন যুক্ত করতে হয়, তবে আপনি নীচে বর্ণিত একটি ক্যালেন্ডার টেবিলের উপর নির্ভর করে একটি ফাংশন তৈরি করতে পারেন:

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


1

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

শুভেচ্ছান্তে!


পারফেক্ট! এই আমি খুঁজছিলাম ছিল। বিশেষ ধন্যবাদ!
ফ্যান্টম

0

এটি আমার পক্ষে কাজ করছে, আমার দেশে শনিবার এবং রবিবার অ-কার্যদিবসের দিন।

আমার জন্য @ স্টার্টডেট এবং @ শেষ তারিখের সময়টি গুরুত্বপূর্ণ।

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

0

এর মতো ফাংশন তৈরি করুন:

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

0
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

শেষ


0

আমি নীচের টিএসকিউএল একটি মোটামুটি মার্জিত সমাধান পেয়েছি (আমার কাছে ফাংশনগুলি চালানোর অনুমতি নেই)। আমি 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*/ 

0

একটি পদ্ধতি হ'ল 'তারিখগুলি হাঁটা' একটি কেস এক্সপ্রেশনের সাথে শুরু করে যা দিনটি শনিবার বা রবিবার না হয় এবং এটি পতাকাঙ্কিত করে কিনা তা পরীক্ষা করে দেখায় (সপ্তাহের দিনের জন্য 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)

0

আমার সমাধান তৈরির জন্য আমি অন্যের কাছ থেকে কিছু ধারণা ধার নিয়েছি। আমি সাপ্তাহিক ছুটির দিন এবং মার্কিন যুক্তরাষ্ট্রীয় ছুটির দিনগুলি উপেক্ষা করতে ইনলাইন কোড ব্যবহার করি। আমার পরিবেশে, এন্ডডেটটি শূন্য হতে পারে তবে এটি কখনও স্টার্টেটের আগে চলে না।

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.