Calculate total business working days between two dates

后端 未结 2 2069
南方客
南方客 2021-01-22 10:49
select  count(distinct(dateadd(d, 0, datediff(d, 0,checktime)))) as workingdays
from departments,
 dbo.USERINFO INNER JOIN dbo.CHECKINOUT ON 
     dbo.USERINFO.USERID =          


        
2条回答
  •  粉色の甜心
    2021-01-22 11:06

    If you only want to exclude weekends then you can simply just exclude these using a conditional count by adding:

    count(distinct case when datepart(weekday, getdate()) <= 5 then date end)
    

    So your query becomes:

    set datefirst 1;
    
    select  count(distinct(dateadd(d, 0, datediff(d, 0,checktime)))) as workingdays,
            count(distinct case when datepart(weekday, getdate()) <= 5 
                                then dateadd(d, 0, datediff(d, 0,checktime)) 
                            end) as weekdays
    from departments,
     dbo.USERINFO INNER JOIN dbo.CHECKINOUT ON 
         dbo.USERINFO.USERID = dbo.CHECKINOUT.USERID
    where  userinfo.name='Gokul Gopalakrishnan' and deptname='GEN/SUP-TBL' 
    and checktime>='2014-05-01' and checktime<='2014-05-30'
    

    HOWEVER I would really recommend adding a calendar table to your database. It makes everything so easy, your query would become:

    SELECT  DaysWorked = COUNT(cio.Date),
            WeekDaysWorked = COUNT(CASE WHEN c.IsWeekDay = 1 THEN cio.Date END),
            WorkingDaysWorked = COUNT(CASE WHEN c.IsWorkingDay = 1 THEN cio.Date END),
            TotalDays = COUNT(*),
            TotalWeekDays = COUNT(CASE WHEN c.IsWeekDay = 1 THEN 1 END),
            TotalWorkingDays = COUNT(CASE WHEN c.IsWorkingDay = 1 THEN 1 END)
    FROM    dbo.Calender AS c
            LEFT JOIN
            (   SELECT  DISTINCT
                        Date = CAST(CheckTime AS DATE)
                FROM    dbo.Departments AS d
                        CROSS JOIN dbo.userInfo AS ui
                        INNER JOIN dbo.CheckInOut AS cio
                            ON cio.UserID = ui.UserID
                WHERE   ui.Name = 'Gokul Gopalakrishnan' 
                AND     d.deptname = 'GEN/SUP-TBL' 
            ) AS cio
                ON c.Date = cio.Date
    WHERE   d.Date >= '2014-05-01'
    AND     d.Date <= '2014-05-30';
    

    This way you can define public holidays, weekends, etc. It is so much more flexible than any other solution.

    EDIT

    I think I misunderstood your original criteria. This should work for you with no calendar table:

    SET DATEFIRST 1;
    
    DECLARE @StartDate DATE = '2014-05-01', 
            @EndDate DATE = '2014-05-30';
    
    DECLARE @Workdays INT = 
        (DATEDIFF(DAY, @StartDate, @EndDate) + 1)
        -(DATEDIFF(WEEK, @StartDate, @EndDate) * 2)
        -(CASE WHEN DATEPART(WEEKDAY, @StartDate) = 7 THEN 1 ELSE 0 END)
        -(CASE WHEN DATEPART(WEEKDAY, @EndDate) = 6 THEN 1 ELSE 0 END);
    
    
    SELECT  WorkingDays = COUNT(DISTINCT CAST(CheckTime AS DATE)),
            BusinessDays = @Workdays
    FROM    dbo.Departments AS d
            CROSS JOIN dbo.userInfo AS ui
            INNER JOIN dbo.CheckInOut AS cio
                ON cio.UserID = ui.UserID
    WHERE   ui.Name = 'Gokul Gopalakrishnan' 
    AND     d.deptname = 'GEN/SUP-TBL' 
    AND     cio.CheckTime >= @StartDate
    AND     cio.CheckTime <= @EndDate;
    

提交回复
热议问题