找到可以重复级别的父子关系

时间:2017-09-27 06:39:27

标签: sql sql-server tsql sql-server-2012

我有一个场景(在SQL Server 2012中),我必须确定给定日期之间的扩展之间的父子关系。我设法将数据转换成可以识别主记录(即Start CallerID和nextCallerID(transfer)),子记录和结束记录(即结束CallID)的格式。见下表。

问题是任何CallID或NextCallID都可以在Master,Sub或End调用的同一天重复。我基本上必须找到正确的呼叫组,并且每组必须重复Master CallID。此外,呼叫可以多次传输,这意味着它可以有许多子记录。

数据:

Timestamp               | CallID      | NextCallID  | Type
------------------------|-------------|-------------|-----
2017-07-26 14:37:24.000 | 37468024    | 37594497    | M
2017-07-26 14:51:27.000 | 37594497    | 37595080    | S
2017-07-26 14:59:30.000 | 37595080    | 37512345    | S
2017-07-26 14:59:59.000 | 37512345    | NULL        | E
2017-07-26 18:59:59.000 | 37594497    | NULL        | M

期望的结果:

Timestamp               | MasterCallID | CallID    | NextCallID | Type
------------------------|------------- |-----------|------------|-------
2017-07-26 14:37:24.000 | 37468024     | 37468024  | 37594497   | Master
2017-07-26 14:51:27.000 | 37468024     | 37594497  | 37595080   | Sub/transfer
2017-07-26 14:59:30.000 | 37468024     | 37595080  | 37512345   | Sub/transfer
2017-07-26 14:59:59.000 | 37468024     | 37512345  | NULL       | End Call
2017-07-26 18:59:59.000 | 37594497     | 37594497  | NULL       | Master

从上面的数据集中可以看出,CallID 37594497是主记录的孩子,然后当天晚些时候是新记录/电话的主人。

如果问题陈述/表格格式不清楚,请道歉。 在这方面的任何援助将不胜感激。

修订:

建议的解决方案不适用于以下场景:

数据:

   Timestamp                | CallID      | NextCallID  | Type
    ------------------------|-------------|-------------|-----
    2017-07-26 07:08:32.000 | 37461343    | 37565836    | M
    2017-07-26 07:31:06.000 | 37565804    | 37565938    | M
    2017-07-26 07:35:23.000 | 37565836    | 37565909    | S
    2017-07-26 07:42:23.000 | 37565909    | NULL        | E
    2017-07-26 07:45:04.000 | 37565938    | 37566044    | S
    2017-07-26 07:52:59.000 | 37566044    | NULL        | E
    2017-07-26 18:14:26.000 | 37565461    | 37565909    | M
    2017-07-26 18:24:48.000 | 37565804    | NULL        | M
    2017-07-26 18:26:11.000 | 37565836    | NULL        | M
    2017-07-26 18:29:23.000 | 37565909    | 37566044    | S
    2017-07-26 18:30:06.000 | 37565938    | NULL        | M
    2017-07-26 18:33:11.000 | 37566044    | NULL        | E

输出(使用CTE查询):

   Timestamp                | MasterCallID| CallID      | NextCallID    | Type
    ------------------------|-------------|-------------|---------------|-------
    2017-07-26 07:08:32.000 | 37461343    | 37461343    | 37565836      | M
    2017-07-26 07:31:06.000 | 37565804    | 37565804    | 37565938      | M
    2017-07-26 07:35:23.000 | 37461343    | 37565836    | 37565909      | S
    2017-07-26 07:42:23.000 | 37461343    | 37565909    | NULL          | E
    2017-07-26 07:42:23.000 | 37565461    | 37565909    | NULL          | E
    2017-07-26 07:45:04.000 | 37565804    | 37565938    | 37566044      | S
    2017-07-26 07:52:59.000 | 37461343    | 37566044    | NULL          | E
    2017-07-26 07:52:59.000 | 37565461    | 37566044    | NULL          | E
    2017-07-26 07:52:59.000 | 37565804    | 37566044    | NULL          | E
    2017-07-26 18:14:26.000 | 37565461    | 37565461    | 37565909      | M
    2017-07-26 18:24:48.000 | 37565804    | 37565804    | NULL          | M
    2017-07-26 18:26:11.000 | 37565836    | 37565836    | NULL          | M
    2017-07-26 18:29:23.000 | 37461343    | 37565909    | 37566044      | S
    2017-07-26 18:29:23.000 | 37565461    | 37565909    | 37566044      | S
    2017-07-26 18:30:06.000 | 37565938    | 37565938    | NULL          | M
    2017-07-26 18:33:11.000 | 37461343    | 37566044    | NULL          | E
    2017-07-26 18:33:11.000 | 37565461    | 37566044    | NULL          | E
    2017-07-26 18:33:11.000 | 37565804    | 37566044    | NULL          | E

期望的输出:

   Timestamp                | MasterCallID| CallID      | NextCallID    | Type
    ------------------------|-------------|-------------|---------------|-------
    2017-07-26 07:08:32.000 | 37461343    | 37461343    | 37565836      | M
    2017-07-26 07:35:23.000 | 37461343    | 37565836    | 37565909      | S
    2017-07-26 07:42:23.000 | 37461343    | 37565909    | NULL          | E
    2017-07-26 07:31:06.000 | 37565804    | 37565804    | 37565938      | M
    2017-07-26 07:45:04.000 | 37565804    | 37565938    | 37566044      | S
    2017-07-26 07:52:59.000 | 37565804    | 37566044    | NULL          | E
    2017-07-26 18:14:26.000 | 37565461    | 37565461    | 37565909      | M
    2017-07-26 18:29:23.000 | 37565461    | 37565909    | 37566044      | S
    2017-07-26 18:33:11.000 | 37565461    | 37566044    | NULL          | E
    2017-07-26 18:26:11.000 | 37565836    | 37565836    | NULL          | M

非常感谢您的协助。

此致

2 个答案:

答案 0 :(得分:0)

更好地阅读您的要求,我认为您必须使用递归查询(CTE)。在递归部分中,它提取所有层次结构。我在最后一栏(M2)中跟踪主要电话。

此查询不是基于我之前回答的呼叫时间顺序。它仅使用CallID和NextCallID,因此您也可以使用相同的时间进行调用层次结构。

;WITH A AS (SELECT Timestamp,CallID,NextCallID,Type, CallID AS MasterCallID
            FROM CALLS WHERE TYPE='M'
            UNION ALL 
            SELECT B.Timestamp,B.CallID,B.NextCallID,B.Type, A.MasterCallID
            FROM CALLS B 
            INNER JOIN A ON A.NEXTCALLID=B.CALLID
            WHERE B.TYPE<>'M')
SELECT  Timestamp
        , MasterCallID  
        , CallID
        , NextCallID
        , CASE Type WHEN 'M' Then 'Master' WHEN 'S' THEN 'Sub/Transfer' WHEN 'E' THEN 'End Call' ELSE '' END AS Type
FROM A 
ORDER BY TIMESTAMP

输出:

+-------------------------+------------+----------+------------+--------------+
|        Timestamp        | MASTERCALL |  CallID  | NextCallID |     Type     |
+-------------------------+------------+----------+------------+--------------+
| 2017-07-26 14:37:24.000 |   37468024 | 37468024 | 37594497   | Master       |
| 2017-07-26 14:51:27.000 |   37468024 | 37594497 | 37595080   | Sub/Transfer |
| 2017-07-26 14:59:30.000 |   37468024 | 37595080 | 37512345   | Sub/Transfer |
| 2017-07-26 14:59:59.000 |   37468024 | 37512345 | NULL       | End Call     |
| 2017-07-26 18:59:59.000 |   37594497 | 37594497 | NULL       | Master       |
+-------------------------+------------+----------+------------+--------------+

问题编辑后的新版本(上述查询可能会创建错误的&#34;链接&#34; call-mastercall):

; WITH A AS (SELECT Timestamp,CallID,NextCallID,Type, CallID AS MasterCallID, Timestamp AS TIMEMASTER 
            FROM CALLS WHERE TYPE='M'
            UNION ALL 
            SELECT B.Timestamp,B.CallID,B.NextCallID,B.Type, A.MasterCallID, A.TIMEMASTER 
            FROM CALLS B 
            INNER JOIN A ON B.CALLID=A.NEXTCALLID AND B.TIMESTAMP>A.TIMESTAMP           
            WHERE B.TYPE<>'M')
SELECT  A.Timestamp
        , A.MasterCallID  
        , A.CallID
        , A.NextCallID
        , CASE A.Type WHEN 'M' Then 'Master' WHEN 'S' THEN 'Sub/Transfer' WHEN 'E' THEN 'End Call' ELSE '' END AS Type
FROM A 
INNER JOIN (SELECT TIMESTAMP, CALLID, MAX(TIMEMASTER) MAXTIMEM FROM A GROUP BY TIMESTAMP, CALLID) C ON A.TIMESTAMP=C.TIMESTAMP AND A.CALLID=C.CALLID AND A.TIMEMASTER = C.MAXTIMEM
ORDER BY TIMEMASTER, TIMESTAMP
;

使用新样本数据输出:

Timestamp                MasterCallID  CallID        NextCallID    Type
------------------------ ------------- ------------- ------------- ------------
2017-07-26 07:08:32.000  37461343      37461343      37565836      Master
2017-07-26 07:35:23.000  37461343      37565836      37565909      Sub/Transfer
2017-07-26 07:42:23.000  37461343      37565909      NULL          End Call
2017-07-26 07:31:06.000  37565804      37565804      37565938      Master
2017-07-26 07:45:04.000  37565804      37565938      37566044      Sub/Transfer
2017-07-26 07:52:59.000  37565804      37566044      NULL          End Call
2017-07-26 18:14:26.000  37565461      37565461      37565909      Master
2017-07-26 18:29:23.000  37565461      37565909      37566044      Sub/Transfer
2017-07-26 18:33:11.000  37565461      37566044      NULL          End Call
2017-07-26 18:24:48.000  37565804      37565804      NULL          Master
2017-07-26 18:26:11.000  37565836      37565836      NULL          Master
2017-07-26 18:30:06.000  37565938      37565938      NULL          Master

答案 1 :(得分:0)

您可以使用grouping SUM来尝试OVER初始查询中的元素:

DECLARE @DataSource TABLE
(
    [Timestamp] DATETIME2
   ,[CallID] BIGINT
   ,[NextCallID] BIGINT
   ,[Type] CHAR(1)
);

INSERT INTO @DataSource ([Timestamp], [CallID], [NextCallID], [Type])
VALUES ('2017-07-26 14:37:24.000', 37468024, 37594497, 'M')
      ,('2017-07-26 14:51:27.000', 37594497, 37595080, 'S')
      ,('2017-07-26 14:59:30.000', 37595080, 37512345, 'S')
      ,('2017-07-26 14:59:59.000', 37512345, NULL, 'E')
      ,('2017-07-26 18:59:59.000', 37594497, NULL, 'M');

SELECT *
      ,SUM(IIF([Type] = 'M', 1, 0)) OVER (ORDER BY [Timestamp] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Group]
FROM @DataSource
ORDER BY [Timestamp] ASC;

enter image description here

了解每次通话的小组,我们只需找到CallID,其中每个小组的TypeM

WITH DataSource AS
(
    SELECT *
          ,SUM(IIF([Type] = 'M', 1, 0)) OVER (ORDER BY [Timestamp] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Group]
    FROM @DataSource
)
SELECT *
      ,MAX(IIF([Type] = 'M', [CallID], NULL)) OVER (PARTITION BY [Group])
FROM DataSource
ORDER BY [Timestamp] ASC;

enter image description here