2016-04-05 1 views
0

Grundsätzlich, was ich versuche, ist Anrufdauer auf SIP-Signalisierung zu holen.MySQL Timediff auf einer Spalte für ausgewählte Datensätze in der Tabelle

Ich habe eine Tabelle mit Datensätzen, wie unten gezeigt und ich versuche, eine SELECT-Anweisung zu schreiben, die die folgende zurück:

id callid date     micro_ts   method duration1 duration2 
------------------------------------------------------------------------------------ 
25 123  2016-04-05 00:00:25  1459814425000320 BYE  00:00:04 3.999876 
46 234  2016-04-05 00:01:25  1459814485000000 BYE  00:00:04 4.000000 

Die ID ist von der ersten BYE für einen bestimmten CallID. CallID ist für jeden einzelnen Anruf immer gleich. 00:00:04 sollte der Unterschied zwischen Datum und 3.999876 der Unterschied zwischen micro_ts sein.

Die SQL sollte einen Datensatz pro Callid zurückgeben. Der schwierige Teil hier ist, dass ich versuche, den Unterschied zwischen den Nachrichten zu bekommen, die Start/Ende des Anrufs anzeigen.

Ich will es Dauer basierend auf „Die ersten Methode = 200 nach method = 183 bis zum ersten BYE“ zurückzukehren oder „Die ersten Methode = 200 nach Methode = 180 und kein Verfahren = 183 sind bis zum ersten BYE gefunden“

Wie kann ich diese Kriterien kombinieren, um das zurückzugeben, was ich für eine Tabelle mit mehreren Anrufen möchte?

Ich habe versucht, SQL als solche zu schreiben:

select * from (
select id, callid, micro_ts, method, min(date) as StartTime, max(date) as EndTime, 
timediff(max(date), min(date)) as duration 
from (select t.*, 
      (select count(*) 
       from tableA t2 
       where t2.date <= t.date and 
        t2.method = 'BYE' 
      ) as grp 
     from tableA t 
    ) t where t.method = '200' 
group by callid, method 
order by 3 desc) z; 

Ich glaube, das funktioniert unter der Annahme, nur alle Anrufe 200 einmal hat und dann ein BYE.

id callid date     micro_ts   method 
--------------------------------------------------------------- 
1 123  2016-04-05 00:00:01  1459814401000025 INVITE 
2 123  2016-04-05 00:00:02  145981440200
3 123  2016-04-05 00:00:03  1459814403000941 INVITE 
4 123  2016-04-05 00:00:04  1459814404000392 INVITE 
5 123  2016-04-05 00:00:05  1459814405000539 INVITE 
6 123  2016-04-05 00:00:06  1459814406000101 404 
7 123  2016-04-05 00:00:07  1459814407000007 INVITE 
8 123  2016-04-05 00:00:08  1459814408000948 404 
9 123  2016-04-05 00:00:09  1459814409000784 100 
10 123  2016-04-05 00:00:10  1459814410000192 183 
11 123  2016-04-05 00:00:11  1459814411000482 183 
12 123  2016-04-05 00:00:12  1459814412000561 183 
13 123  2016-04-05 00:00:13  1459814413000392 183 
14 123  2016-04-05 00:00:14  1459814414000751 180 
15 123  2016-04-05 00:00:15  1459814415000012 180 
16 123  2016-04-05 00:00:16  1459814416000384 180 
17 123  2016-04-05 00:00:17  1459814417000498 180 
18 123  2016-04-05 00:00:18  1459814418000533 183 
19 123  2016-04-05 00:00:19  1459814419000841 183 
20 123  2016-04-05 00:00:20  1459814420000492 183 
21 123  2016-04-05 00:00:21  1459814421000444 200   * FIRST 200 after 183 
22 123  2016-04-05 00:00:22  1459814422000901 200   | 
23 123  2016-04-05 00:00:23  1459814423000294 ACK   | 
24 123  2016-04-05 00:00:24  1459814424000732 ACK   | 
25 123  2016-04-05 00:00:25  1459814425000320 BYE   * FIRST BYE 
26 123  2016-04-05 00:00:26  1459814426000020 BYE 
27 123  2016-04-05 00:00:27  1459814427000391 200 
28 123  2016-04-05 00:00:28  145981442800
29 234  2016-04-05 00:01:01  1459814461000000 INVITE 
30 234  2016-04-05 00:01:02  1459814462000000 407 
31 234  2016-04-05 00:01:03  1459814463000000 INVITE 
32 234  2016-04-05 00:01:04  1459814464000000 INVITE 
33 234  2016-04-05 00:01:05  1459814465000000 INVITE 
34 234  2016-04-05 00:01:06  1459814466000000 404 
35 234  2016-04-05 00:01:07  1459814467000000 INVITE 
36 234  2016-04-05 00:01:08  1459814468000000 404 
37 234  2016-04-05 00:01:09  1459814469000000 100 
38 234  2016-04-05 00:01:10  1459814470000000 183 
39 234  2016-04-05 00:01:11  1459814471000000 183 
40 234  2016-04-05 00:01:12  1459814472000000 183 
41 234  2016-04-05 00:01:13  1459814473000000 183 
42 234  2016-04-05 00:01:14  1459814474000000 180 
43 234  2016-04-05 00:01:15  1459814475000000 180 
44 234  2016-04-05 00:01:16  1459814476000000 180 
45 234  2016-04-05 00:01:17  1459814477000000 180 
46 234  2016-04-05 00:01:21  1459814481000000 200   * FIRST 200 after 180 whern no 183 is present 
47 234  2016-04-05 00:01:22  1459814482000000 200   | 
48 234  2016-04-05 00:01:23  1459814483000000 ACK   | 
49 234  2016-04-05 00:01:24  1459814484000000 ACK   | 
50 234  2016-04-05 00:01:25  1459814485000000 BYE   * FIRST BYE 
51 234  2016-04-05 00:01:26  1459814486000000 BYE 
52 234  2016-04-05 00:01:27  1459814487000000 200 
53 234  2016-04-05 00:01:28  1459814488000000 200 
+0

Sie haben gesagt, Sie arbeiten auf der Annahme, theres nur 1 200 Anruf, aber an beiden Orten markiert Sie 200, Theres ein 200 in der Zeile unter der gleichen CallID. Canyou machen irgendwelche Annahmen wie die gleiche Anruf-ID wird nicht in einer Minute passieren, aber dass die Tschüss Antwort wird in <1 Minute getan werden? – BugFinder

+0

Hallo @BugFinder - Mein SQL-Beispiel verwendet diese Annahme, aber ich möchte dies geändert. Die Annahme ist, dass für jede CallID nur 200 angezeigt wird, wenn ein Anruf angenommen wird. Diese Annahme wird nicht immer gültig sein. Ich möchte, dass die Dauer basierend auf "Die erste Methode = 200 nach Methode = 183 bis zum ersten BYE" oder "Die erste Methode = 200 nach Methode = 180 und keine Methode = 183 bis zum ersten BYE" zurückgegeben wird. –

+0

Lassen Sie mich versuchen, umzuformulieren .. "Dauer zwischen 200 und BYE für eindeutige CallIDs, wenn 200 nach 183 erscheint, oder 180, wenn 183 fehlt, und vor BYE" –

Antwort

1

Ich habe ein zu gehen hatte und es kann einige Guss Probleme mit den CASE-Ausdrücke sein, aber das sollte man die meisten der Weg dorthin gelangen:

SELECT id, 
     callid 
     start_date, 
     start_ms, 
     end_date, 
     end_ms, 
     end_date - start_date AS duration1, 
     end_ms - start_ms AS duration2 
FROM (
    SELECT 
      @same_call := @callid = callid, 
      @has_ended := @same_call AND (@has_ended OR @has_bye) AS has_ended, 
      @has_18x := (@has_18x AND @same_call) OR method IN ('180','183'), 
      @has_200 := (@has_200 AND @same_call) OR (@has_18x AND method = '200'), 
      @has_bye := (@has_bye AND @same_call) OR (@has_200 AND method = 'BYE') AS has_bye, 

      @start_date := CASE 
          WHEN @has_200 THEN COALESCE(@start_date, `date`) 
         END AS start_date, 
      @start_ms := CASE 
         WHEN @has_200 THEN COALESCE(@start_ms, micro_ts) 
         END AS start_ms, 
      @end_date := CASE 
         WHEN @has_bye THEN COALESCE(@end_date, `date`) 
         END AS end_date, 
      @end_ms := CASE 
         WHEN @has_bye THEN COALESCE(@end_ms, micro_ts) 
        END AS end_ms, 

      id, 
      @callid := callid AS callid   

    FROM sip_signal 

    JOIN (
     SELECT @callid := NULL, 
      @has_ended := FALSE, 
      @has_18x := FALSE, 
      @has_200 := FALSE, 
      @has_bye := FALSE, 
      @start_date := NULL, 
      @start_ms := NULL, 
      @end_date := NULL, 
      @end_ms := NULL     
     ) init 

ORDER BY callid, micro_ts 

    ) sip_call 
WHERE has_bye 
    AND NOT has_ended 

Wenn Sie das Innenleben sehen möchten Führen Sie einfach das innere SELECT (+ JOIN und ORDER BY) aus.

+1

Das funktioniert wie ein Charme - und gibt die richtige Dauer, wenn Sie ändern "end_date - start_date als duration1" um ein Timediff und die @ has_200 und @has_bye für _ms zu 'micro_ts' zu enthalten. Vielen Dank! –

+0

Ich möchte auch hinzufügen, es war schön geschrieben und verständlich für uns Nicht-Experten. Reines Gold. –

0

ich mySQL .. zur Hand nicht haben, so könnte dies ernsthafte Müll sein aber das ist, was in meinem Kopf ich es aufschreiben wollte, bevor er weg lief - wie gesagt, scheint es chaotisch

select callid, ,datediff(data,case when start1<=start2 then start1 else start2 end) as duration from 
    (select callid,call_from,call_to,min(starta) as start1,min(startb) as start2,min(data) from 
     (select callid,call_from,call_to, 
      count(case when method = 180 THEN date END) starta, 
      count(case when method = 183 THEN date END) startb, 
      count(case when method = 200 THEN date END) data, 
     from mydata) group by callid, call_from,call_to)) 

Hilft das? Gibt dir das Ideen?

Verwandte Themen