T-SQL |计算日期之间的小时数,但忽略周末的小时数,仅计算8-18小时

时间:2017-07-13 11:06:33

标签: sql-server tsql datediff

我正在尝试计算两个日期之间的差异,不包括周末,只计算从晚上8点到早上6点的时间。我想计算天,小时和分钟的差异。

为此我有这个:

DECLARE @Start_Date DATETIME
DECLARE @End_Date DATETIME

SET @Start_Date = '2017-06-23 10:43:41.000'
SET @End_Date = '2017-06-27 11:58:52.000'

SELECT (DATEDIFF(dd, @Start_Date, @End_Date) + 1)
                -(DATEDIFF(wk, @Start_Date, @End_Date) * 2)
                -(CASE WHEN DATENAME(dw, @Start_Date) = 'Sunday' THEN 1 ELSE 0 END)
                -(CASE WHEN DATENAME(dw, @End_Date) = 'Saturday' THEN 1 ELSE 0 END) AS [Time to First Atualization- Days],
            datediff(hour, @Start_Date, @End_Date) - (datediff(wk, @Start_Date, @End_Date) * 48) -
                case when datepart(dw, @Start_Date)  = 1 then 1 else 0 end +
                case when datepart(dw, @End_Date)  = 1 then 1 else 0 end AS [Time to First Atualization- Hours],
                datediff(minute, @Start_Date, @End_Date) - (datediff(wk, @Start_Date, @End_Date) * 2880) -
                case when datepart(dw, @Start_Date)  = 1 then 1 else 0 end +
                case when datepart(dw, @End_Date)  = 1 then 1 else 0 end AS [Time to First Atualization- Minutes]

查询返回正确值但计算小时数和分钟数错误的天数...

我该如何解决这个问题?

谢谢!

1 个答案:

答案 0 :(得分:1)

我从零开始做了一些事情,它似乎涵盖了你所有的需求,但如果缺少某些东西你可以更新我们。

考虑到这是一个新的开始并且来自不同的角度,您可能会发现某些技术或想法。此外,它对我来说似乎更简单,但也许那是因为我正在审查自己的工作......

最后一点,我将依赖于我之前阅读过的技巧,它以行方式应用MINMAX,抽象示例:

SELECT MAX([value]) AS [MAX], MIN([value]) AS [MIN]
FROM (
VALUES (CURRENT_TIMESTAMP), (@Start_Date), (@End_Date), (NULL), (0)
) AS [data]([value])

首先,考虑一下开始时的时间量&结束日期:

SELECT MinutesExcludingStartAndEndDays = MAX([value])
FROM (VALUES (0), ((DATEDIFF(DAY, @Start_Date, @End_Date) - 1) * 840)) AS [data]([value])

其次,计算开始日期间的时间,而不是晚上8点(如果两天匹配,则为或结束时间):

SELECT MinutesOnStartDay = DATEDIFF(MINUTE, @Start_Date, MIN([value]))
FROM (VALUES (@End_Date), (DATETIMEFROMPARTS(YEAR(@Start_Date), MONTH(@Start_Date), DAY(@Start_Date), 20, 0, 0, 0))) AS [data]([value])

第三个非常类似于第二个,但请注意,如果开始和结束日期相同,我们不应该计算第二个和第三个。我决定用第三个CASE语句处理它:

SELECT MinutesOnEndDayIfNotStartDay = CASE DATEDIFF(DAY, @Start_Date, @End_Date) WHEN 0 THEN 0 ELSE DATEDIFF(MINUTE, MAX([value]), @End_Date) END
FROM (VALUES (@Start_Date), (DATETIMEFROMPARTS(YEAR(@End_Date), MONTH(@End_Date), DAY(@End_Date), 6, 0, 0, 0))) AS [data]([value])

第四,如果开始或结束日期在周末降落,则应将其从那里推开:

DECLARE @Mod int

SET @Mod = CONVERT(int, @Start_Date) % 7
IF @Mod IN (5, 6)
    SET @Start_Date = DATEADD(DAY, CASE @Mod WHEN 5 THEN 2 WHEN 6 THEN 1 ELSE 0/0 END, DATETIMEFROMPARTS(YEAR(@Start_Date), MONTH(@Start_Date), DAY(@Start_Date), 6, 0, 0, 0))

SET @Mod = CONVERT(int, @End_Date) % 7
IF @Mod IN (5, 6)
    SET @End_Date = DATEADD(DAY, CASE @Mod WHEN 5 THEN -1 WHEN 6 THEN -2 ELSE 0/0 END, DATETIMEFROMPARTS(YEAR(@End_Date), MONTH(@End_Date), DAY(@End_Date), 20, 0, 0, 0))

最后,周末日完全包含在你的目标期内的问题,因为看看this question,从那里的投票我只能猜测他们已经解决了。