SQL:如何将时间存入轮班时间?

问题描述 投票:0回答:1

我真的需要帮助来找到正确的 SQL 逻辑以获得预期的结果(第三张表)。 我必须从链接到表 B 的表 A 中存储时间,其中包含存在轮班时间。

在我的练习中,将时间存储到早班或下午班并不重要。 我可以机械地叠加到轮班时间,例如按项目编号排序。

表 A - 有效时间

姓名 项目编号 小时数量
马丁先生 项目 1 1
马丁先生 项目 2 2
马丁先生 项目 3 1
史密斯先生 项目 1 4

表 B - 在场轮班时间

姓名 上午开始时间 AM结束时间 下午开始时间 下午结束时间
马丁先生 9:00 12:00 14:00 17:00
史密斯先生 10:00 12:00 13:00 16:00

我想得到的结果:

姓名 项目编号 开始时间 结束时间 小时数量
马丁先生 项目 1 9:00 10:00 1
马丁先生 项目 2 10:00 12:00 2
马丁先生 项目 3 14:00 15:00 1
马丁先生 没有项目 15:00 17:00 2
史密斯先生 项目 1 10:00 12:00 2
史密斯先生 项目 1 13:00 15:00 2
史密斯先生 没有项目 15:00 16:00 1

如果你能帮助我,我想提供啤酒;)

非常感谢。

sql oracle oracle10g
1个回答
0
投票

您可以取消 AM 和 PM 班次,然后计算班次和项目的总小时数,并在时间重叠时加入两者(在 Oracle 11g 上测试,因为 10g 非常旧):

WITH shifts AS (
  SELECT name,
         shift,
         start_time,
         end_time,
         SUM(EXTRACT(HOUR FROM end_time - start_time))
           OVER (PARTITION BY name ORDER BY start_time)
         - EXTRACT(HOUR FROM end_time - start_time) AS total_start_time,
         SUM(EXTRACT(HOUR FROM end_time - start_time))
           OVER (PARTITION BY name ORDER BY start_time) AS total_end_time
  FROM   shift_time
  UNPIVOT (
    (start_time, end_time)
    FOR shift IN (
      (am_start_time, am_end_time) AS 'AM',
      (pm_start_time, pm_end_time) AS 'PM'
    )
  )
),
hours AS (
  SELECT name,
         project_number,
         hours,
         SUM(hours) OVER (PARTITION BY name ORDER BY project_number) - hours
           AS start_hour,
         SUM(hours) OVER (PARTITION BY name ORDER BY project_number)
           AS end_hour
  FROM   effective_hours
)
SELECT s.name,
       h.project_number,
       s.shift,
       s.start_time + NUMTODSINTERVAL(GREATEST(start_hour, total_start_time) - total_start_time, 'HOUR') AS start_time,
       s.start_time + NUMTODSINTERVAL(LEAST(end_hour, total_end_time) - total_start_time, 'HOUR') AS end_time
FROM   shifts s
       INNER JOIN hours h
       ON (   s.name = h.name
          AND s.total_start_time < h.end_hour
          AND s.total_end_time   > h.start_hour );

其中,对于示例数据:

CREATE TABLE effective_hours (name, project_number, hours) AS
SELECT 'ALICE', 'PROJECT 1', 1 FROM DUAL UNION ALL
SELECT 'ALICE', 'PROJECT 2', 2 FROM DUAL UNION ALL
SELECT 'ALICE', 'PROJECT 3', 1 FROM DUAL UNION ALL
SELECT 'BERYL', 'PROJECT 1', 4 FROM DUAL UNION ALL
SELECT 'CAROL', 'PROJECT 1', 7 FROM DUAL;

CREATE TABLE shift_time (name, AM_start_time, AM_end_time, PM_start_time, PM_end_time) AS
SELECT 'ALICE', INTERVAL '9' HOUR,  INTERVAL '12' HOUR, INTERVAL '14' HOUR, INTERVAL '17' HOUR FROM DUAL UNION ALL
SELECT 'BERYL',  INTERVAL '10' HOUR, INTERVAL '12' HOUR, INTERVAL '13' HOUR, INTERVAL '16' HOUR FROM DUAL UNION ALL
SELECT 'CAROL',  INTERVAL '9' HOUR, INTERVAL '12' HOUR, INTERVAL '13' HOUR, INTERVAL '19' HOUR FROM DUAL;

哪些输出:

姓名 PROJECT_NUMBER 转变 START_TIME END_TIME
爱丽丝 项目 2 上午 +000000000 10:00:00.000000000 +000000000 12:00:00.000000000
爱丽丝 项目 1 上午 +000000000 09:00:00.000000000 +000000000 10:00:00.000000000
爱丽丝 项目 3 下午 +000000000 14:00:00.000000000 +000000000 15:00:00.000000000
绿柱石 项目 1 上午 +000000000 10:00:00.000000000 +000000000 12:00:00.000000000
绿柱石 项目 1 下午 +000000000 13:00:00.000000000 +000000000 15:00:00.000000000
卡罗尔 项目 1 上午 +000000000 09:00:00.000000000 +000000000 12:00:00.000000000
卡罗尔 项目 1 下午 +000000000 13:00:00.000000000 +000000000 17:00:00.000000000

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.