【问题标题】:T-SQL | Calculate the number of hours between dates but ignore the hours from Weekend and only count 8-18 hoursT-SQL |计算日期之间的小时数,但忽略周末的小时数,只计算 8-18 小时
【发布时间】:2017-07-13 11:06:33
【问题描述】:

我正在尝试计算不包括周末的两个日期之间的差异,并且只计算从晚上 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]

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

我该如何解决这个问题?

谢谢!

【问题讨论】:

  • 你能解释一下你在查询中的逻辑是什么吗?
  • 我想知道员工在工作时间内的工作日数、小时数和分钟数。他只在工作日工作,并且安排在晚上 8 点和早上 6 点之间。
  • @PedroAlves 如果我运行你的脚本,我有 49 个。你在期待什么?
  • 我期待 21 小时。原因:第一天 8 小时(上午 10 点至下午 6 点)+ 第二天 10 小时 - 2017 年 7 月 26 日(上午 8 点至下午 6 点)+ 第三天 3 小时 2017 年 7 月 27 日 - 上午 8 点至下午 6 点(上午 8 点至晚上 11 点)
  • 您在第二条评论中写了 8pm(实际上是 8am)和 6am(实际上是 6pm)

标签: sql-server tsql datediff


【解决方案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])

Third 与 second 非常相似,但请注意,如果开始和结束日期相同,则不应同时计算 second 和 third。我决定在第三个中使用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,从那里的投票我只能猜他们已经解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2023-03-11
    • 2018-11-15
    • 2017-01-08
    • 1970-01-01
    相关资源
    最近更新 更多