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 server 基于持续时间分割记录_Sql Server_Tsql - Fatal编程技术网

Sql server 基于持续时间分割记录

Sql server 基于持续时间分割记录,sql-server,tsql,Sql Server,Tsql,我有一张表格,里面有我们呼叫中心的代理在各个州花费的时间。 以下是其中一条记录的示例: AgentName, AgentState, BeginTransitionTime, EndTransitionTime, BeginHour, EndHour Breana Rascon(994840), Work Time, 3/14/16 7:56:19 AM, 3/14/16 11:02:51 AM, 7, 11 我希望将上述记录拆分为5条记录,如下所示: Breana Rascon(9

我有一张表格,里面有我们呼叫中心的代理在各个州花费的时间。 以下是其中一条记录的示例:

AgentName, AgentState, BeginTransitionTime, EndTransitionTime, BeginHour,   EndHour

Breana Rascon(994840), Work Time, 3/14/16 7:56:19 AM, 3/14/16 11:02:51 AM, 7,   11
我希望将上述记录拆分为5条记录,如下所示:

Breana Rascon(994840), Work Time, 3/14/16 7:56:19 AM, 3/14/2016 7:59:59 AM, 7,  7

Breana Rascon(994840), Work Time, 3/14/16 8:00:00 AM, 3/14/2016 8:59:59 AM, 8,  8

Breana Rascon(994840), Work Time, 3/14/16 9:00:00 AM, 3/14/2016 9:59:59 AM, 9,  9

Breana Rascon(994840), Work Time, 3/14/16 10:00:00 AM, 3/14/2016 10:59:59 AM,   10, 10

Breana Rascon(994840), Work Time, 3/14/16 11:00:00 AM, 3/14/16 11:02:51 AM, 11, 11
我一开始使用的是游标,当记录在两个小时内被分割时,游标工作得很好,但除此之外,代码开始失控。任何帮助都将不胜感激


谢谢大家!

如果使用数字表,它是一个简单的联接和一些转换。否则,您将需要一个CTE或其他窗口功能

数字Z表

记录分割


如果你想使用一个递归的CTE,它看起来像这样

WITH    cte
          AS (SELECT    [AgentName],
                        [AgentState],
                        [BeginTransitionTime],
                        [EndTransitionTime],
                        [NewEndTransitionTime] = DATEADD(second,-1,DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + 1,0)),
                        [BeginHour],
                        [EndHour] = [BeginHour]
              FROM      agents
              UNION ALL
              SELECT    [AgentName],
                        [AgentState],
                        DATEADD(hour,DATEDIFF(hour,0,[NewEndTransitionTime]) + 1,0),
                        [EndTransitionTime],
                        [NewEndTransitionTime] = CASE WHEN [EndTransitionTime] < [NewEndTransitionTime] THEN [EndTransitionTime]
                                                      ELSE DATEADD(second,-1,DATEADD(hour,DATEDIFF(hour,0,[NewEndTransitionTime]) + 2,0))
                                                 END,
                        [BeginHour] + 1,
                        [EndHour] + 1
              FROM      cte
              WHERE     DATEADD(hour,DATEDIFF(hour,0,[NewEndTransitionTime]) + 1,0) < [EndTransitionTime]
             )
    SELECT  [AgentName],
            [AgentState],
            [BeginTransitionTime],
            [EndTransitionTime] = CASE WHEN [EndTransitionTime] < [NewEndTransitionTime] THEN [EndTransitionTime] ELSE [NewEndTransitionTime] END,
            [BeginHour],
            [EndHour]
    FROM    cte
这也可以使用数字表来完成。。虽然只有少量记录时速度较慢,但如果数据集较大,速度可能会更快

WITH    E1(N)
          AS (SELECT    1
              UNION ALL
              SELECT    1
              UNION ALL
              SELECT    1
              UNION ALL
              SELECT    1
              UNION ALL
              SELECT    1
             ),                          
        E2([Hour])
          AS (SELECT    ROW_NUMBER() OVER (ORDER BY (SELECT NULL
                                                    )) Num
              FROM      E1 a,
                        E1 b
             )
    SELECT  [AgentName],
            [AgentState],
            [BeginTransitionTime] = CASE WHEN a.BeginHour = E2.[Hour] 
                                        THEN [BeginTransitionTime] 
                                        ELSE DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + (E2.[Hour] - a.BeginHour),0) 
                                    END,
            [EndTransitionTime] =   CASE WHEN [EndTransitionTime] < DATEADD(second, -1 , DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + (E2.[Hour] - a.BeginHour + 1),0))
                                        THEN [EndTransitionTime] 
                                        ELSE DATEADD(second, -1 , DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + (E2.[Hour] - a.BeginHour + 1),0))
                                    END,
            [BeginHour] = E2.[Hour],
            [EndHour] = E2.[Hour]
    FROM    agents a
            JOIN E2 ON E2.[Hour] BETWEEN a.BeginHour AND a.EndHour

拆分为5的标准是什么?这对所有人都一样吗?数字表的要点不是在CTE中重新创建,而是将其保存在操作数据库中,并使用它而不是CTE。而且在规模上要快得多。如果您没有数字表或不想使用数字表,那么您的第一个示例就是我使用的。@SteveMangiameli我尝试了所有3种方法,而永久数字表在小范围内是最慢的。。但是我没有用更多的记录来测试它。。这是不科学的,但这是基于代理表中的1000行。。
select 
      AgentName
    , AgentState
    , BeginTransitionTime = CASE WHEN numVal = BeginHour then BeginTransitionTime else cast(cast(BeginTransitionTime as date) as nvarchar(10)) +' '+cast(numVal as nvarchar(2))+':00:00' end 
    , EndTransitionTime   = CASE WHEN numVal = EndHour   then EndTransitionTime   else cast(cast(ENDTRANSITIONTIME   as date) as nvarchar(10)) +' '+cast(numVal as nvarchar(2))+':59:59' end 
    , BeginHour           = numVal
    , EndHour             = numVal
from tbl_agentTime a
    join numberz n on n.numVal >= a.BeginHour and n.numVal<= a.EndHour
WITH    cte
          AS (SELECT    [AgentName],
                        [AgentState],
                        [BeginTransitionTime],
                        [EndTransitionTime],
                        [NewEndTransitionTime] = DATEADD(second,-1,DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + 1,0)),
                        [BeginHour],
                        [EndHour] = [BeginHour]
              FROM      agents
              UNION ALL
              SELECT    [AgentName],
                        [AgentState],
                        DATEADD(hour,DATEDIFF(hour,0,[NewEndTransitionTime]) + 1,0),
                        [EndTransitionTime],
                        [NewEndTransitionTime] = CASE WHEN [EndTransitionTime] < [NewEndTransitionTime] THEN [EndTransitionTime]
                                                      ELSE DATEADD(second,-1,DATEADD(hour,DATEDIFF(hour,0,[NewEndTransitionTime]) + 2,0))
                                                 END,
                        [BeginHour] + 1,
                        [EndHour] + 1
              FROM      cte
              WHERE     DATEADD(hour,DATEDIFF(hour,0,[NewEndTransitionTime]) + 1,0) < [EndTransitionTime]
             )
    SELECT  [AgentName],
            [AgentState],
            [BeginTransitionTime],
            [EndTransitionTime] = CASE WHEN [EndTransitionTime] < [NewEndTransitionTime] THEN [EndTransitionTime] ELSE [NewEndTransitionTime] END,
            [BeginHour],
            [EndHour]
    FROM    cte
WITH    E1(N)
          AS (SELECT    1
              UNION ALL
              SELECT    1
              UNION ALL
              SELECT    1
              UNION ALL
              SELECT    1
              UNION ALL
              SELECT    1
             ),                          
        E2([Hour])
          AS (SELECT    ROW_NUMBER() OVER (ORDER BY (SELECT NULL
                                                    )) Num
              FROM      E1 a,
                        E1 b
             )
    SELECT  [AgentName],
            [AgentState],
            [BeginTransitionTime] = CASE WHEN a.BeginHour = E2.[Hour] 
                                        THEN [BeginTransitionTime] 
                                        ELSE DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + (E2.[Hour] - a.BeginHour),0) 
                                    END,
            [EndTransitionTime] =   CASE WHEN [EndTransitionTime] < DATEADD(second, -1 , DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + (E2.[Hour] - a.BeginHour + 1),0))
                                        THEN [EndTransitionTime] 
                                        ELSE DATEADD(second, -1 , DATEADD(hour,DATEDIFF(hour,0,[BeginTransitionTime]) + (E2.[Hour] - a.BeginHour + 1),0))
                                    END,
            [BeginHour] = E2.[Hour],
            [EndHour] = E2.[Hour]
    FROM    agents a
            JOIN E2 ON E2.[Hour] BETWEEN a.BeginHour AND a.EndHour