Расчет бизнес-различий в SQL в виде дней, часов и минут - SQL Server - PullRequest
0 голосов
/ 04 июня 2019

С помощью приведенной ниже функции я получаю результат как 00:09:10, однако я хочу, чтобы результат был как 01: 00: 10.

Таким образом, часы считаются 1 днем.

Например, если часов 30, тогда будет 03:03:00 и т. Д.

fn_GetHolidayMinutes: получение выходного за считанные минуты между двумя датами и страной

CREATE FUNCTION [dbo].[fn_GetHolidayMinutes] 
    (@StartDate DATETIME,
     @EndDate DATETIME,
     @CountryId BIGINT)
RETURNS BIGINT
AS
BEGIN
    DECLARE @OUTPUT BIGINT;
    DECLARE @HolidayList TABLE (HolidaysDate DATE)

    -- Create Table #HolidayList
    -- (
    --     HolidaysDate date
    -- )

    DECLARE @Date1 DATE, @Date2 DATE

    DECLARE holiday_cursor CURSOR FOR     
        SELECT StartDate,EndDate 
        FROM Holidays 
        WHERE IsActive = 1 
          AND CountryId = @CountryId 
          AND ((StartDate BETWEEN @StartDate AND @EndDate) OR
               (EndDate BETWEEN @StartDate AND @EndDate))

    OPEN HOLIDAY_CURSOR    

    FETCH NEXT FROM HOLIDAY_CURSOR INTO @Date1, @Date2    

    WHILE @@FETCH_STATUS = 0    
    BEGIN 
        --INSERT INTO  #HolidayList  
        INSERT INTO @HolidayList
            SELECT DATEADD(DAY, number, @Date1) [Date]
            FROM master..spt_values
            WHERE type = 'P'
              AND DATEADD(DAY, number, @Date1) <= @Date2

        FETCH NEXT FROM HOLIDAY_CURSOR INTO @Date1, @Date2   
    END     

    CLOSE HOLIDAY_CURSOR;    
    DEALLOCATE HOLIDAY_CURSOR;

    (SELECT @OUTPUT= COUNT(DISTINCT HolidaysDate) 
     FROM @HolidayList
     WHERE HolidaysDate BETWEEN @StartDate AND @EndDate
       AND DATEPART(dw, HolidaysDate) NOT IN (SELECT DISTINCT number 
                                              FROM master..spt_values 
                                              WHERE number BETWEEN 1 and 7
                                                AND number NOT IN (SELECT WorkingDay 
                                                                   FROM WorkingDays 
                                                                   WHERE CountryId = @CountryId AND IsActive = 1)
                                          ))
    ---print @OUTPUT; --this will give in days

    --get the output in minutes
    RETURN @OUTPUT * (SELECT TOP 1 STUFF(WorkingHours, 2, 2, '') 
                      FROM dbo.WorkingDays 
                      WHERE CountryId = @CountryId) * 60;
END

fn_GetWorkingDayMinuts:

CREATE FUNCTION [dbo].[fn_GetWorkingDayMinuts] 
    (@StartDate DATETIME,
     @EndDate DATETIME,
     @CountryId BIGINT)
--RETURNS BIGINT
RETURNS VARCHAR(250)
AS
BEGIN
    DECLARE @Temp BIGINT
    SET @Temp = 0

    DECLARE @FirstDay DATE
    SET @FirstDay = CONVERT(DATE, @StartDate, 112)

    DECLARE @LastDay DATE
    SET @LastDay = CONVERT(DATE, @EndDate, 112)

    DECLARE @StartTime TIME
    SET @StartTime = CONVERT(TIME, @StartDate)

    DECLARE @FinishTime TIME
    SET @FinishTime = CONVERT(TIME, @EndDate)

    DECLARE @WorkStart TIME
    SET @WorkStart =  (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
    WorkStartTime FROM WorkingDays WHERE CountryId=@CountryId), 120)))

    DECLARE @WorkFinish TIME
    SET @WorkFinish = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
    WorkEndTime FROM WorkingDays WHERE CountryId=@CountryId), 120)))

    DECLARE @DailyWorkTime BIGINT
    SET @DailyWorkTime = DATEDIFF(MINUTE, @WorkStart, @WorkFinish)

    IF (@StartTime<@WorkStart)
    BEGIN
        SET @StartTime = @WorkStart
    END
    IF (@FinishTime>@WorkFinish)
    BEGIN
        SET @FinishTime=@WorkFinish
    END
    IF (@FinishTime<@WorkStart)
    BEGIN
        SET @FinishTime=@WorkStart
    END
    IF (@StartTime>@WorkFinish)
    BEGIN
        SET @StartTime = @WorkFinish
    END

    DECLARE @CurrentDate DATE
    SET @CurrentDate = @FirstDay
    DECLARE @LastDate DATE
    SET @LastDate = @LastDay

    WHILE(@CurrentDate<=@LastDate)
    BEGIN       
        --IF (DATEPART(dw, @CurrentDate)!=1 AND DATEPART(dw, @CurrentDate)!=7)
        IF(DATEPART(dw, @CurrentDate) IN (SELECT distinct number FROM master..spt_values WHERE number BETWEEN 1 and 7
                                          AND number NOT IN (SELECT 
      WorkingDay FROM WorkingDays where CountryId=@CountryId and IsActive=1)
                                          ))
        BEGIN
            IF (@CurrentDate!=@FirstDay) AND (@CurrentDate!=@LastDay)
            BEGIN
                SET @Temp = @Temp + @DailyWorkTime
            END
            --IF it starts at startdate and it finishes not this date find diff between work finish and start as minutes
            ELSE IF (@CurrentDate=@FirstDay) AND (@CurrentDate!=@LastDay)
            BEGIN
                SET @Temp = @Temp + DATEDIFF(MINUTE, @StartTime, @WorkFinish)
            END

            ELSE IF (@CurrentDate!=@FirstDay) AND (@CurrentDate=@LastDay)
            BEGIN
            SET @Temp = @Temp + DATEDIFF(MINUTE, @WorkStart, @FinishTime)
            END
            --IF it starts and finishes in the same date
            ELSE IF (@CurrentDate=@FirstDay) AND (@CurrentDate=@LastDay)
            BEGIN
            SET @Temp = DATEDIFF(MINUTE, @StartTime, @FinishTime)
            END
        END
           SET @CurrentDate = DATEADD(day, 1, @CurrentDate)
    END

    -- Return the result of the function
    IF @Temp<0
    BEGIN
        SET @Temp=0
    END
    --RETURN @Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, DATEDIFF(dd, 0, @StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
   @EndDate)),@CountryId))
    --RETURN @Temp

    DECLARE @theMinutes INT
    DECLARE @Result VARCHAR(250)

    SET @theMinutes = @Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, 
  DATEDIFF(dd, 0, @StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
  @EndDate)),@CountryId))

     --SET @Result= concat((@theMinutes / 540),':' , (@theMinutes % 540) / 
  60, ':', (@theMinutes % 60))
    SET @Result= concat((@theMinutes / ((SELECT TOP 1 
  STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
  CountryId=@CountryId) * 60)),':' , (@theMinutes % ((SELECT TOP 1
  STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
  CountryId=@CountryId) * 60)) / 60, ':', (@theMinutes % 60))

    RETURN @Result
END

Так где же изменить результат на

BUSINESS HOURS          CREATE DATE & TIME      FIRST APPLY (DATE & TIME)       TAT TIME CALCULATION                RESULT
08h00-17h00: 9hrs/day   12-FEB-19 14:20         13-FEB-19 14:30                 00:02:40 + 00:06:30 = 00:09:10      01:00:10
...