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