2017-09-27 2 views
0

J'ai un scénario (dans SQL Server 2012) dans lequel je dois déterminer la relation parent-enfant entre les extensions d'un jour donné. J'ai réussi à obtenir les données dans un format qui peut identifier une fiche (c'est-à-dire Start CallerID et nextCallerID (transfert)), des sous-enregistrements et un enregistrement de fin (c'est-à-dire qui termine l'identificateur CallID). Voir le tableau ci-dessous.Recherche d'une relation parent-enfant où les niveaux peuvent être répétés

Le problème est que n'importe quel CallID ou NextCallID peut être répété plus tard le même jour en tant qu'appel Master, Sub ou End. Je dois fondamentalement trouver le bon groupe d'appels et le Master CallID doit être répété par groupe. En outre, un appel peut être transféré plusieurs fois, ce qui signifie qu'il peut avoir plusieurs enregistrements Sub.

données:

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 

Résultat souhaité:

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 

Comme vous pouvez le voir sur les données ci-dessus fixées, CallID 37594497 était un enfant à un enregistrement maître, puis plus tard dans la journée était un maître d'un nouvel enregistrement/appel. Toutes nos excuses si l'énoncé de problème/le format de la table n'est pas clair.

Toute aide à cet égard serait grandement appréciée.


Amendement:

Les solutions proposées ne fonctionne pas avec le scénario suivant:

données:

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 

(au moyen de requête 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 

sortie souhaité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 

vous serions reconnaissants de votre aide.

Cordialement

+0

ce n'est pas "Les solutions proposées ne fonctionnent pas avec le scénario suivant". Vous avez changé le scénario d'origine. Donc, je pense que vous devriez voter la réponse si elle correspond à votre requête originale. Ensuite, nous pouvons essayer de vous aider pour cette nouvelle demande. – etsa

+0

Veuillez lire l'introduction à S.O. et apprendre à formater le texte. Puis ajoutez une brève description de ce que vous avez demandé dans votre "nouvelle" question et montrez votre effort (dans ce cas, qu'avez-vous essayé de faire pour résoudre votre nouvelle requête à partir de la requête en réponse?) – etsa

+0

ça, mais ce n'est pas très facile (au moins au moins on dirait que oui ...) – etsa

Répondre

0

Lire mieux à vos besoins, je pense que vous devez utiliser une requête récursive (CTE). Dans la partie récursive, il extrait toutes les hiérarchies. Je suis l'appel Master dans la dernière colonne (M2).

Cette requête n'est pas basée sur l'ordre chronologique des appels en tant que réponse précédente. Il fonctionne en utilisant seulement CallID et NextCallID, de sorte que vous pouvez avoir la hiérarchie des appels en utilisant la même heure aussi.

;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 

Sortie:

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

Nouvelle version après modification de la question (ci-dessus requête peut créer mal appeler-mastercall "lien"):

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

sortie avec de nouvelles données de l'échantillon:

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

Merci etsa, je vais essayer avec plus de permutations et vous faire savoir si cela fonctionne. – solidawe

+0

@Wazimh Dans quelques minutes, je posterai une autre requête. Je pense que ce dernier correspondra le mieux à vos besoins. – etsa

+0

@Wazimh voir ma réponse mise à jour. – etsa

0

Vous pouvez grouping les éléments de votre requête initiale à l'aide SUM avec 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

Connaissant le groupe de chaque appel, nous avons seulement besoin de fonder CallID, où Type est M pour chaque groupe:

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

Grâce à gotqn, votre solution fonctionne également avec ce jeu de données fourni. Ma seule préoccupation est le regroupement par timeStamp uniquement lors de l'utilisation de jeux de données beaucoup plus volumineux en production. Va tester cela et fournir des commentaires. – solidawe

+0

votre requête a cessé de fonctionner avec quelques scénarios. S'il vous plaît voir l'amendement à ma question ci-dessus. Appréciez-le. – solidawe