0

我有执行不同任务的用户数据。我想根据用户 ID 和任务 ID 对这些数据进行分组,以获取每个任务的开始和结束时间。当员工更改为另一个任务时,应该有一个新的行,其中包含新的开始和结束时间。

示例简化数据集:

用户身份 任务标识 date_time_stamp(升序)
1 任务-A 16/6/2021 04:17:00
1 任务-A 16/6/2021 04:19:00
1 任务-A 16/6/2021 04:27:00
1 任务-B 16/6/2021 04:31:00
1 任务-B 16/6/2021 04:33:00
1 任务-B 16/6/2021 04:36:00
1 任务-A 16/6/2021 04:42:00
1 任务-A 16/6/2021 04:44:00

示例结果

用户身份 任务标识 first_dtm last_dtm
1 任务-A 16/6/2021 04:17:00 16/6/2021 04:27:00
1 任务-B 16/6/2021 04:31:00 16/6/2021 04:36:00
1 任务-A 16/6/2021 04:42:00 16/6/2021 04:44:00

我知道我应该使用一些结合 GROUP BY 的 min() 和 max() 函数。但是,在此示例中,按用户 ID 和任务 ID 分组将导致任务 A 仅占一行。

4

1 回答 1

2

从 Oracle 12 开始,您可以使用MATCH_RECOGNIZE

SELECT *
FROM   table_name
MATCH_RECOGNIZE(
  PARTITION BY userid
  ORDER BY date_time_stamp
  MEASURES
    FIRST(taskid) AS taskid,
    FIRST(date_time_stamp) AS start_date,
    LAST(date_time_stamp) AS end_date
  ONE ROW PER MATCH
  PATTERN ( same_task+ )
  DEFINE same_task AS FIRST(taskid) = taskid
)

在此之前,您可以使用ROW_NUMBER分析函数和聚合:

SELECT userid,
       taskid,
       MIN(date_time_stamp) AS start_date,
       MAX(date_time_stamp) AS end_date
FROM   (
  SELECT t.*,
         ROW_NUMBER() OVER ( PARTITION BY userid ORDER BY date_time_stamp )
           - ROW_NUMBER() OVER ( PARTITION BY userid, taskid ORDER BY date_time_stamp )
           AS grp
  FROM   table_name t
)
GROUP BY userid, taskid, grp
ORDER BY userid, start_date

其中,对于您的示例数据:

CREATE TABLE table_name ( userid, taskid, date_time_stamp ) AS
SELECT 1, 'task-A', DATE '2021-06-16' + INTERVAL '04:17:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-A', DATE '2021-06-16' + INTERVAL '04:19:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-A', DATE '2021-06-16' + INTERVAL '04:27:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-B', DATE '2021-06-16' + INTERVAL '04:31:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-B', DATE '2021-06-16' + INTERVAL '04:33:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-B', DATE '2021-06-16' + INTERVAL '04:36:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-A', DATE '2021-06-16' + INTERVAL '04:42:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 1, 'task-A', DATE '2021-06-16' + INTERVAL '04:44:00' HOUR TO SECOND FROM DUAL

两个输出:

用户身份 任务ID 开始日期 结束日期
1 任务-A 2021-06-16 04:17:00 2021-06-16 04:27:00
1 任务-B 2021-06-16 04:31:00 2021-06-16 04:36:00
1 任务-A 2021-06-16 04:42:00 2021-06-16 04:44:00

db<>在这里摆弄

于 2021-06-16T12:12:37.787 回答