2016-03-21 7 views
0

У меня есть эта таблица, которая содержит время, проведенное в разных штатах для агентов в нашем Call-центре. Вот пример одной из записей:Сплит-записи, основанные на длительности времени

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 

Я начал использоваться курсор, который работал очень хорошо, когда запись была разделена за 2 часа, но больше, чем это, и код начал выходить из-под контроля. Любая помощь вообще будет высоко оценена.

Спасибо!

+0

что критерии разделения на 5?, Это же для всех? – TheGameiswar

ответ

0

Если вы используете таблицу чисел, это простое объединение и некоторые преобразования. В противном случае вам понадобится CTE или какая-либо другая функция окон.

Numberz стол

DECLARE @UpperLimit INT = 1000000; 

IF OBJECT_ID('dbo.numberz','U') IS NULL 
BEGIN 
    CREATE TABLE dbo.numberz (numVal INT); 

    WITH n(rn) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id]) 
     FROM sys.all_columns AS s1 
     CROSS JOIN sys.all_columns AS s2 
    ) 
    INSERT dbo.numberz 
    SELECT [numVAl] = 0 
    UNION ALL 
    SELECT rn 
    FROM n 
    WHERE rn <= @UpperLimit; 

    CREATE UNIQUE CLUSTERED INDEX uix_numVal ON dbo.numberz([numVAl]); 
END 

Создание Таблица

CREATE TABLE tbl_agentTime 
(
     AgentName   NVARCHAR(255) 
    , AgentState   NVARCHAR(255) 
    , BeginTransitionTime DATETIME 
    , EndTransitionTime DATETIME 
    , BeginHour   INT 
    , EndHour    INT 
) 

INSERT tbl_agentTime 
VALUES ('BREANA RASCON(994840)', 'WORK TIME', '2016-03-14 7:56:19', '2016-03-14 11:02:51', 7, 11) 

Запись Split

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 
0

Если вы хотите использовать Рекурсивный 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 

SQL Fiddle Demo

Это также можно сделать с помощью таблицы чисел .. Хотя это медленнее всего лишь несколько записей, это может быть быстрее больших наборов данных.

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 

SQL Fiddle Demo

+0

Точка таблицы чисел не должна (повторно) создавать в CTE, она должна быть в базе данных операций и использовать ее вместо CTE. И это намного быстрее в масштабе. Если у вас нет таблицы номеров или вы не хотите ее использовать, то ваш первый пример будет тем, с чем я пошел. –

+0

@SteveMangiameli я пробовал все 3 подхода, а таблица постоянных номеров была самой медленной в небольшом масштабе .. но я не тестировал ее, используя более чем несколько записей .. http://i.stack.imgur.com/ eNE30.png – JamieD77

+0

это не научный, но он основан на 1000 строк в таблице операторов. http://i.stack.imgur.com/hKDOV.png – JamieD77

Смежные вопросы