Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何从时间段创建段_Sql_Sql Server_Tsql_Sql Server 2016 - Fatal编程技术网

Sql 如何从时间段创建段

Sql 如何从时间段创建段,sql,sql-server,tsql,sql-server-2016,Sql,Sql Server,Tsql,Sql Server 2016,我有两种活动类型:任务、聊天。每种活动类型都有一个优先级,其中10是最高优先级 我有每项活动的开始时间和结束时间 我需要确定代理在任何给定时间正在积极进行的活动。当两个活动重叠时,具有最高优先级的活动被视为代理正在处理的活动 我解决这个问题的最初想法是根据开始时间和结束时间以及活动重叠的时间,将活动时间划分为多个部分。然后,针对每个具有最高优先级的活动段 例如:09:00-09:15聊天,09:15-09:30聊天,09:30-09:45任务 然而,我真的不知道如何在SQL中实现这一点。 我对“

我有两种活动类型:任务、聊天。每种活动类型都有一个优先级,其中10是最高优先级

我有每项活动的开始时间和结束时间

我需要确定代理在任何给定时间正在积极进行的活动。当两个活动重叠时,具有最高优先级的活动被视为代理正在处理的活动

我解决这个问题的最初想法是根据开始时间和结束时间以及活动重叠的时间,将活动时间划分为多个部分。然后,针对每个具有最高优先级的活动段

例如:09:00-09:15聊天,09:15-09:30聊天,09:30-09:45任务

然而,我真的不知道如何在SQL中实现这一点。 我对“缺口和孤岛”做了一些研究,但没有找到任何可以转化为解决这个问题的例子

我想知道是否有人能给我提供关于解决这个问题的最佳方法和可能的解决方案的建议,以便我能够理解解决方案并实施它

我的数据

预期最终产出

情景2 任务在聊天前后都有一个活动段

DECLARE @ActivityLog TABLE (Activity VARCHAR(8), Priority INT, StartTime DATETIME, EndTime DATETIME)

INSERT INTO @ActivityLog VALUES ('TASK', 7, '2019/07/01 09:00', '2019/07/01 10:00')
INSERT INTO @ActivityLog VALUES ('CHAT', 10, '2019/07/01 09:15', '2019/07/01 09:45');
情景2预期产出


当我们最多有两个重叠的句点时,下面的代码就起作用了。如果您需要更多的重叠句点,您需要更改代码以使用递归公共表表达式

其思想是使用左连接获得重叠,然后根据项目的优先级应用不同的逻辑

这很简单,但很丑陋。我添加了更多的案例和测试,希望不会遗漏任何内容

DECLARE @ActivityLog TABLE (Activity VARCHAR(4), Priority INT, StartTime DATETIME, EndTime DATETIME)

INSERT INTO @ActivityLog 
VALUES ('CHAT', 10, '2019/07/01 09:00', '2019/07/01 09:30') 
      ,('TASK', 5, '2019/07/01 09:15', '2019/07/01 09:20')
      --
      ,('CHAT', 8, '2019/07/01 19:30', '2019/07/01 20:30')
      --
      ,('TASK', 7, '2019/07/02 09:00', '2019/07/02 10:00')
      ,('CHAT', 10, '2019/07/02 09:15', '2019/07/02 09:30')
      --
      ,('CHAT', 10, '2019/12/01 09:00', '2019/12/01 09:30') 
      ,('TASK', 5, '2019/12/01 09:15', '2019/12/01 09:20');


WITH DataSourceWithRowID AS
(
    SELECT *
         ,ROW_NUMBER() OVER (ORDER BY [StartTime]) AS [row_id]
    FROM @ActivityLog
),
DataSource AS
(
    SELECT S.[Activity] AS [S_Activity], S.[Priority] AS [S_Priority], S.[StartTime] AS [S_StartTime], S.[EndTime] AS [S_EndTime], S.[row_id] AS [S_row_id]
          ,E.[Activity] AS [E_Activity], E.[Priority] AS [E_Priority], E.[StartTime] AS [E_StartTime], E.[EndTime] AS [E_EndTime], E.[row_id] AS [E_row_id]
    FROM DataSourceWithRowID S
    LEFT JOIN DataSourceWithRowID E
        ON E.[StartTime] > S.[StartTime] 
        AND E.[StartTime] < S.[EndTime]
)
-- case 1 - handle 1
SELECT [S_Activity], [S_Priority], [S_StartTime], [E_StartTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime < E_EndTime

UNION ALL

-- case 1 - handle 2
SELECT [S_Activity], [S_Priority], [E_StartTime], [S_EndTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime < E_EndTime

UNION ALL

-- case 1 - handle 3
SELECT [E_Activity], [E_Priority], [S_EndTime], [E_EndTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime < E_EndTime

UNION ALL

-- case 1 - handle 4 -- sub period with low priorty -> consume by parent
SELECT [S_Activity], [S_Priority], [S_StartTime], [S_EndTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime > E_EndTime

UNION ALL

-- case 2 - no overlapping
SELECT [S_Activity], [S_Priority], [S_StartTime], [S_StartTime]
FROM DataSource
WHERE [S_row_id] NOT IN (SELECT [E_row_id] FROM DataSource WHERE [E_row_id] IS NOT NULL)
    AND [E_row_id] IS NULL

UNION ALL

-- case 3 - handle 1
SELECT S_Activity, S_Priority, S_StartTime, E_StartTime
FROM DataSource 
WHERE S_Priority < E_Priority

UNION ALL

-- case 3 - handle 2
SELECT  E_Activity
       ,E_Priority
       ,E_StartTime
       ,IIF(S_EndTime > E_EndTime,  E_EndTime, S_EndTime)
FROM DataSource 
WHERE S_Priority < E_Priority

UNION ALL

-- case 3 - handle 3
SELECT IIF(S_EndTime > E_EndTime,  S_Activity, E_Activity)
      ,IIF(S_EndTime > E_EndTime,  S_Priority, E_Priority)
      ,IIF(S_EndTime > E_EndTime,  E_EndTime, S_EndTime)
      ,IIF(S_EndTime > E_EndTime,  S_EndTime, E_EndTime)       
FROM DataSource 
WHERE S_Priority < E_Priority

活动的开始和结束时间是否总是15分钟?如果没有,那么它将如何显示在预期输出中?Hi@Squirrel它不总是在15分钟的间隔内。这将在预期输出中显示,与上面类似,但分钟将显示各自的开始/结束时间。例如09:01开始和09:11结束,然后是09:11开始和10:27结束,如果活动时间是这样的话。根据上一个示例,预期结果是什么样的?您能在示例数据和预期结果中更新吗?嗨@Squirrel为了简单起见,我在示例数据中使用了15分钟的时间间隔,但是活动的开始和结束时间可以随时发生,因为它取决于代理启动/停止活动的时间。@J.Bradow第二种情况-为什么聊天时间从15分钟延长到15分钟30至15至45?Hi@gotqn我已使用以下数据对此进行了测试,但未返回预期结果:“任务”,7,“2019/07/01 09:00”,“2019/07/01 10:00”,“聊天”,10,“2019/07/01 09:00”,“2019/07/01 09:45”
DECLARE @ActivityLog TABLE (Activity VARCHAR(8), Priority INT, StartTime DATETIME, EndTime DATETIME)

INSERT INTO @ActivityLog VALUES ('TASK', 7, '2019/07/01 09:00', '2019/07/01 10:00')
INSERT INTO @ActivityLog VALUES ('CHAT', 10, '2019/07/01 09:15', '2019/07/01 09:45');
+------------------+------------------+----------+
|     StartTime    |      EndTime     | Activity |
+------------------+------------------+----------+
| 2019/07/01 09:00 | 2019/07/01 09:15 |   TASK   |
+------------------+------------------+----------+
| 2019/07/01 09:15 | 2019/07/01 09:45 |   CHAT   |
+------------------+------------------+----------+
| 2019/07/01 09:45 | 2019/07/01 10:00 |   TASK   |
+------------------+------------------+----------+
DECLARE @ActivityLog TABLE (Activity VARCHAR(4), Priority INT, StartTime DATETIME, EndTime DATETIME)

INSERT INTO @ActivityLog 
VALUES ('CHAT', 10, '2019/07/01 09:00', '2019/07/01 09:30') 
      ,('TASK', 5, '2019/07/01 09:15', '2019/07/01 09:20')
      --
      ,('CHAT', 8, '2019/07/01 19:30', '2019/07/01 20:30')
      --
      ,('TASK', 7, '2019/07/02 09:00', '2019/07/02 10:00')
      ,('CHAT', 10, '2019/07/02 09:15', '2019/07/02 09:30')
      --
      ,('CHAT', 10, '2019/12/01 09:00', '2019/12/01 09:30') 
      ,('TASK', 5, '2019/12/01 09:15', '2019/12/01 09:20');


WITH DataSourceWithRowID AS
(
    SELECT *
         ,ROW_NUMBER() OVER (ORDER BY [StartTime]) AS [row_id]
    FROM @ActivityLog
),
DataSource AS
(
    SELECT S.[Activity] AS [S_Activity], S.[Priority] AS [S_Priority], S.[StartTime] AS [S_StartTime], S.[EndTime] AS [S_EndTime], S.[row_id] AS [S_row_id]
          ,E.[Activity] AS [E_Activity], E.[Priority] AS [E_Priority], E.[StartTime] AS [E_StartTime], E.[EndTime] AS [E_EndTime], E.[row_id] AS [E_row_id]
    FROM DataSourceWithRowID S
    LEFT JOIN DataSourceWithRowID E
        ON E.[StartTime] > S.[StartTime] 
        AND E.[StartTime] < S.[EndTime]
)
-- case 1 - handle 1
SELECT [S_Activity], [S_Priority], [S_StartTime], [E_StartTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime < E_EndTime

UNION ALL

-- case 1 - handle 2
SELECT [S_Activity], [S_Priority], [E_StartTime], [S_EndTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime < E_EndTime

UNION ALL

-- case 1 - handle 3
SELECT [E_Activity], [E_Priority], [S_EndTime], [E_EndTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime < E_EndTime

UNION ALL

-- case 1 - handle 4 -- sub period with low priorty -> consume by parent
SELECT [S_Activity], [S_Priority], [S_StartTime], [S_EndTime]
FROM DataSource
WHERE S_Priority > E_Priority
    AND S_EndTime > E_EndTime

UNION ALL

-- case 2 - no overlapping
SELECT [S_Activity], [S_Priority], [S_StartTime], [S_StartTime]
FROM DataSource
WHERE [S_row_id] NOT IN (SELECT [E_row_id] FROM DataSource WHERE [E_row_id] IS NOT NULL)
    AND [E_row_id] IS NULL

UNION ALL

-- case 3 - handle 1
SELECT S_Activity, S_Priority, S_StartTime, E_StartTime
FROM DataSource 
WHERE S_Priority < E_Priority

UNION ALL

-- case 3 - handle 2
SELECT  E_Activity
       ,E_Priority
       ,E_StartTime
       ,IIF(S_EndTime > E_EndTime,  E_EndTime, S_EndTime)
FROM DataSource 
WHERE S_Priority < E_Priority

UNION ALL

-- case 3 - handle 3
SELECT IIF(S_EndTime > E_EndTime,  S_Activity, E_Activity)
      ,IIF(S_EndTime > E_EndTime,  S_Priority, E_Priority)
      ,IIF(S_EndTime > E_EndTime,  E_EndTime, S_EndTime)
      ,IIF(S_EndTime > E_EndTime,  S_EndTime, E_EndTime)       
FROM DataSource 
WHERE S_Priority < E_Priority