2017-09-27 16 views
0

我有一个场景(在SQL Server 2012中),我必须确定给定日期的扩展之间的父子关系。我设法将数据转换成能够识别主记录(即,开始呼叫者ID和下一呼叫ID(传送)),子记录和结束记录(即结束呼叫ID)的格式。见下表。找到可重复级别的亲子关系

问题是,任何CallID或NextCallID都可以在Master,Sub或End调用当天晚些时候重复使用。我基本上必须找到正确的呼叫组,并且每个组必须重复主呼叫ID。此外,呼叫可以多次传送,这意味着它可以有很多Sub记录。

数据:

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 

正如你可以从上面的数据集看,呼叫标识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 

将非常感谢您的帮助。

问候

+0

这不是“建议的解决方案不适用于以下情况”。您更改了原始方案。所以,我认为如果它对应于您的原始查询,您应该投票回答。然后,我们可以尝试帮助您解决这一新问题。 – etsa

+0

请阅读S.O的介绍。并学习格式化文本。然后在你的“新”问题中添加一个简短的描述,并显示你的努力(在这种情况下,你试图做什么来解决你的新请求从查询开始回答?) – etsa

+0

我正在处理它,但它不是很容易(至少现在看起来如此......) – etsa

回答

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  | 
+-------------------------+------------+----------+------------+--------------+ 

问题编辑(上面的查询可以创建错误的 “链接” 呼叫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 
+0

谢谢etsa,我会给它一个更多的排列,并让你知道它是否有效。 – solidawe

+0

@Wazimh几分钟后我会发布另一个查询。我认为后者将最适合您的要求。 – etsa

+0

@Wazimh看到我更新的答案。 – etsa

0

可以使用SUMOVER尝试grouping在初始查询的元素:

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

+0

感谢gotqn,您的解决方案也适用于此提供的数据集。我唯一担心的是只有在生产中使用更大的数据集时才按timeStamp进行分组。将对此进行测试并提供反馈。 – solidawe

+0

您的查询停止了一些场景。请参阅上面对我的问题的修正。欣赏它。 – solidawe