给定两个时间戳,计算这些日期之间经过的工作小时数

bil*_*ett 3 google-bigquery

给定表中的两个时间戳,start_time, end_time计算它们之间发生的总工作时间。

工作时间在您选择的单独表格中定义。

Hen*_*eng 6

假设您有一个工作时间表,以下是 Snowflake SQL 中的解决方案:

select
  t.id
  , sum(datediff(‘second’, 
               -- calculate the max of the two start time
               (case when t.start <= 
                          w.working_day_start_timestamp
                     then w.working_day_start_timestamp
                     else t.start
                end),
               -- calculate the min of the two end times
               (case when t.end >= 
                          w.working_day_end_timestamp
                     then w.working_day_end_timestamp
                     else t.end 
                end)
               )) / 3600 -- convert to hourly
  as working_hour_diff
from 
  working_days_times w,
  cross join time_intervals t
where -- select all intersecting intervals
  (
   t.start <= w.working_day_end_timestamp
   and
   t.end >= w.working_day_start_timestamp
  )
and -- select only working days
  w.is_working_day
group by
  t.id
Run Code Online (Sandbox Code Playgroud)

这是一篇文章,详细介绍了在 SQL 中和作为雪花中的 Javascript UDF 实现这一点的更多细节:

https://medium.com/dandy-engineering-blog/how-to-calculate-the-number-of-working-hours-between-two-timestamps-in-sql-b5696de66e51


Mik*_*ant 5

以下示例适用于 BigQuery 标准 SQL

#standardSQL
WITH `project.dataset.working_hours` AS (
  SELECT 1 weekday, 'Sun' DAY, NULL start_time, NULL end_time UNION ALL
  SELECT 2, 'Mon', TIME(9, 0, 0), TIME(17, 0, 0) UNION ALL
  SELECT 3, 'Tue', TIME(9, 0, 0), TIME(17, 0, 0) UNION ALL
  SELECT 4, 'Wed', TIME(9, 0, 0), TIME(17, 0, 0) UNION ALL
  SELECT 5, 'Thu', TIME(9, 0, 0), TIME(17, 0, 0) UNION ALL
  SELECT 6, 'Fri', TIME(9, 0, 0), TIME(17, 0, 0) UNION ALL
  SELECT 7, 'Sat', TIME(9, 0, 0), TIME(15, 0, 0) 
), `project.dataset.availability` AS (
  SELECT 'Tom' name, TIMESTAMP '2018-01-10 12:38:04' start_time, TIMESTAMP '2018-02-11 10:38:04' end_time UNION ALL
  SELECT 'Mike', TIMESTAMP '2018-01-01 12:35:00', TIMESTAMP '2018-01-01 14:35:00' UNION ALL
  SELECT 'Sam', TIMESTAMP '2018-01-06 12:35:00', TIMESTAMP '2018-01-07 14:35:00' 
), full_days_minutes AS (
  SELECT name, 
    SUM(TIME_DIFF(h.end_time, h.start_time, MINUTE)) minutes
  FROM `project.dataset.availability` a, 
    UNNEST(GENERATE_DATE_ARRAY(DATE(start_time), DATE(end_time))) DAY
  JOIN `project.dataset.working_hours` h
    ON h.weekday = EXTRACT(DAYOFWEEK FROM DAY)
  GROUP BY name
), corrections AS (
  SELECT name,
    IFNULL(CASE -- correction for start time 
      WHEN TIME(a.start_time) > x.end_time THEN TIME_DIFF(x.end_time, x.start_time, MINUTE)
      WHEN TIME(a.start_time) < x.start_time THEN 0
      ELSE TIME_DIFF(TIME(a.start_time), x.start_time, MINUTE)
    END, 0) + 
    IFNULL(CASE -- correction for end time 
      WHEN TIME(a.end_time) < y.start_time THEN TIME_DIFF(y.end_time, y.start_time, MINUTE)
      WHEN TIME(a.end_time) > y.end_time THEN 0
      ELSE TIME_DIFF(y.end_time, TIME(a.end_time), MINUTE)
    END, 0)
    AS correction
  FROM  `project.dataset.availability` a
  JOIN `project.dataset.working_hours` x ON x.weekday = EXTRACT(DAYOFWEEK FROM a.start_time)
  JOIN `project.dataset.working_hours` y ON y.weekday = EXTRACT(DAYOFWEEK FROM a.end_time)
)
SELECT name, minutes - correction AS elapsed_minutes, 
  ROUND((minutes - correction) / 60, 2) elapsed_hours
FROM full_days_minutes JOIN corrections USING(name)  
Run Code Online (Sandbox Code Playgroud)

结果为

Row name    elapsed_minutes elapsed_hours    
1   Tom              12,622        210.37    
2   Mike                120          2   
3   Sam                 145          2.42         
Run Code Online (Sandbox Code Playgroud)

注意:代码假定可用性和工作时间表中的 start_time <= end_time