16

我的表有示例数据,我需要计算两列中两个时间戳之间的营业时间。营业时间:上午 9:00 至下午 5:00,忽略周六和周日,我不考虑公共假期。有人可以提供一些关于如何实现这一目标的指导吗?我想要第 3 列中所述的所需输出,日期格式为:yyyy-mm-dd

    Created date             Updated date         Business hrs
    2012-03-05 9:00am   2012-03-05 3:00pm             6
    2012-03-05 10:00am  2012-03-06 10:00am            9
    2012-03-09 4:00pm   2012-03-19 10:00am            2
4

4 回答 4

24

问题是不应该考虑公共假期,所以这个答案就是这样做的 - 计算考虑到周末的营业时间,但忽略可能的公共假期。

如果您需要考虑公共假期,您需要有一个单独的表格来列出公共假期的日期,这可能会因年而异,因州而异或因国家而异。主要公式可能保持不变,但您需要从结果中减去在给定日期范围内的公共假期的小时数。

让我们创建一个表,其中包含一些涵盖各种情况的示例数据:

CREATE TABLE T (CreatedDate datetime, UpdatedDate datetime);

INSERT INTO T VALUES
('2012-03-05 09:00:00', '2012-03-05 15:00:00'), -- simple part of the same day
('2012-03-05 10:00:00', '2012-03-06 10:00:00'), -- full day across the midnight
('2012-03-05 11:00:00', '2012-03-06 10:00:00'), -- less than a day across the midnight
('2012-03-05 10:00:00', '2012-03-06 15:00:00'), -- more than a day across the midnight
('2012-03-09 16:00:00', '2012-03-12 10:00:00'), -- over the weekend, less than 7 days
('2012-03-06 16:00:00', '2012-03-15 10:00:00'), -- over the weekend, more than 7 days
('2012-03-09 16:00:00', '2012-03-19 10:00:00'); -- over two weekends

在 MS SQL Server 中,我使用以下公式:

SELECT
    CreatedDate,
    UpdatedDate,
    DATEDIFF(minute, CreatedDate, UpdatedDate)/60.0 -
    DATEDIFF(day,    CreatedDate, UpdatedDate)*16 -
    DATEDIFF(week,   CreatedDate, UpdatedDate)*16 AS BusinessHours
FROM T

这会产生以下结果:

+-------------------------+-------------------------+---------------+
|       CreatedDate       |       UpdatedDate       | BusinessHours |
+-------------------------+-------------------------+---------------+
| 2012-03-05 09:00:00     | 2012-03-05 15:00:00     | 6             |
| 2012-03-05 10:00:00     | 2012-03-06 10:00:00     | 8             |
| 2012-03-05 11:00:00     | 2012-03-06 10:00:00     | 7             |
| 2012-03-05 10:00:00     | 2012-03-06 15:00:00     | 13            |
| 2012-03-09 16:00:00     | 2012-03-12 10:00:00     | 2             |
| 2012-03-06 16:00:00     | 2012-03-15 10:00:00     | 50            |
| 2012-03-09 16:00:00     | 2012-03-19 10:00:00     | 42            |
+-------------------------+-------------------------+---------------+

它可以工作,因为在 SQL Server 中,返回指定startdateenddate之间跨越的指定datepartDATEDIFF边界的计数。

每天有 8 个工作时间。我计算两个日期之间的总小时数,然后减去午夜数乘以每天 16 个非营业时间,然后减去周末数乘以 16(周六 + 周日为 8 + 8 个营业时间)。

它还假设给定的开始和结束日期/时间是在工作时间内。

在 MySQL 中,最接近的等价物是TIMESTAMPDIFF,但它的工作方式不同。它有效地计算以秒为单位的差异,并除以(丢弃小数部分)所选单位的秒数。

所以,为了得到我们需要的结果,我们可以计算TIMESTAMPDIFF一些锚日期时间和CreatedDate和而不是直接计算和UpdatedDate之间的差异。CreatedDateUpdatedDate

我选择2000-01-03 00:00:00了星期一。您可以选择任何其他周一(或周日,如果您的一周从周日开始)午夜作为锚定日期。

MySQL 查询变为(参见SQL Fiddle):

SELECT
    CreatedDate,
    UpdatedDate,

    TIMESTAMPDIFF(MINUTE, CreatedDate, UpdatedDate)/60.0 -

    16*(
        TIMESTAMPDIFF(DAY,    '2000-01-03',UpdatedDate)-
        TIMESTAMPDIFF(DAY,    '2000-01-03',CreatedDate)
    ) -

    16*(
        TIMESTAMPDIFF(WEEK,   '2000-01-03',UpdatedDate)-
        TIMESTAMPDIFF(WEEK,   '2000-01-03',CreatedDate)
    ) AS BusinessHours

FROM T
于 2015-10-20T03:09:54.500 回答
4

创建一个名为 BusinessHours 的表,其中一个名为 Hour 的列包含一个日期时间。将 Hour 设为主键。编写一个流程,用一年中的每个营业时间(2012-01-02 00:90:00, 2012-01-02 00:10:00等)填充它。这应该不难,因为规则很简单。这听起来像是很多数据,但从总体上看,它不是(一年只有 8760 小时 - 即使您的日期时间每个需要 8 个字节,这也是惊人的 60kB)。确保安排作业以保持其填充。

然后:

Select
  y.CreatedDate,
  y.UpdatedDate,
  Count(*) as BusinessHours
From
  YourTable y
    Inner Join
  BusinessHours h
    On h.Hour >= y.CreatedDate And h.Hour < y.UpdatedDate
Group By
  y.CreatedDate,
  y.UpdatedDate

如果您确实考虑过公共假期,这也为您提供了一种相当简单的方法 - 只需将行从 BusinessHours 表中取出。

于 2012-11-17T00:13:32.920 回答
1

使用 datediff 计算开始时间和结束时间之间的差异,然后减去(带负数的 date_add 时间)非工作时间:周末 24 天,工作日 16 天,预计结束和开始日期需要额外计算。一天是否是周末,可以用 dayofweek 方法指定。

于 2015-10-20T15:45:54.317 回答
0

尝试

SELECT (FLOOR(DATEDIFF (UpdatedDate, CreatedDate) / 7) * 5 + MOD (DATEDIFF (UpdatedDate, CreatedDate), 7)) * 8 +
       TIMEDIFF (TIME (UpdatedDate), TIME(CreatedDate))
FROM YourTable

以上内容并不完整,因为它只是“估计”周末......但它应该让你开始......另一种选择是使用有效营业时间表(有关详细信息,请参阅来自 Laurence 的答案)。

有关参考,请参阅MySQL 文档

于 2012-11-17T00:17:15.157 回答