2009-04-10 15 views
0

Tabelle Ich versuche, analytische Ergebnisse von Sprachaufzeichnungen zu erhalten. Jeder Aufruf (eine Zeile) hat eine Dauer in Sekunden (nur int-Wert, nicht datetime). Ich versuche, Anzahl der Datensätze von 15 Sekunden umspannt wie folgt gruppiert zu erhalten:Zeilen zählen in SQL stament mit Gruppierung nach incrementalen Variablen

+-------------------+ 
|Period | Count  | 
+-------------------+ 
| 0-15 | 213421 | 
|15-30 | 231123 | 
|30-45 | 1234  | 
+-------------------+ 

Startet der Periode 0, Ende ist 86400.

Ich habe einige Kombinationen versucht, mit Variablen für Start Einstellung und beende und vergrößere sie dann um 15, aber ich bin nicht sehr erfolgreich und ich kann nicht verstehen, was falsch läuft.

Bitte helfen Sie. Vielen Dank!

+0

nicht klar genug Informationen für eine Antwort ... –

+0

Welche RDBMS verwenden Sie? – Quassnoi

Antwort

2

In MySQL:

SELECT CONCAT(span * 15, '-', span * 15 + 15), COUNT(*) AS cnt 
FROM (
     SELECT v.*, FLOOR(period/15) AS span 
     FROM voice_calls v 
     ) q 
GROUP BY 
     span 

UPDATE:

Die Lösung Sie arbeiten wird gebucht, da vorausgesetzt wird immer mehr als 5760 Zeilen sein.

Aber Sie besser einen Dummy rowset von 5760 Zeilen erstellen und verwenden Sie es in OUTER JOIN:

CREATE TABLE spans (span INT NOT NULL PRIMARY KEY); 

INSERT 
INTO spans 
VALUES (0), 
     (1), 
     ... 
     (5759) 

SELECT span * 15, COUNT(*) 
FROM spans 
LEFT JOIN 
     calls 
ON  call.duration >= span * 15 
     AND call.duration < span * 15 + 15 
GROUP BY 
     span 

es effizienter sein und gesund, wie es kann weder Unterlauf (wenn weniger als 5760 Reihen in calls), noch zu viel Zeit, wenn dort Millionen von Reihen sind.

+0

Niemals daran gedacht, FLOOR-Funktion nachzuschlagen, diese Abfrage sieht gut aus, aber leider funktioniert es nicht. # 1248 - Jede abgeleitete Tabelle muss ihren eigenen Alias ​​haben Anscheinend MySQL benötigt alle abgeleiteten Tabellen Aliase haben –

+0

Ein kleines Problem mit dieser Abfrage (IMHO) - wenn es keine Datensätze in einer bestimmten Gruppe/Bereich gibt es keine Zeile über diese Gruppe/Spanne im Ergebnis. –

+0

@ marko1980: Ja, MySQL erfordert dies. – Quassnoi

0

Ich denke, eine Abfrage wie diese sollte funktionieren; Hier finden Sie die Ergebnisse selbst auf dem Display schwenken müssen allerdings (zB wird diese Abfrage, um die horizontal Ergebnisse, werden Sie sie vertikal haben anzuzeigen):

SELECT 
    SUM(CASE WHEN CallLength BETWEEN 0 AND 15 THEN CallLength ELSE 0 END) AS ZeroToFifteen, 
    SUM(CASE WHEN CallLength BETWEEN 16 AND 30 THEN CallLength ELSE 0 END) AS FifteenToThirty 
FROM CallTable 

Aber nach dem erneuten Lesen der Frage, Fall setzen Aussagen zu 86400 bis ist wahrscheinlich die Frage aus ... Oh gut :)

0

Das endlich gearbeitet:

SET @a:=-15, @b:=0; 
SELECT t.start_time, t.end_time, count(c.duration) 
FROM calls c, 
     (
     SELECT (@a:[email protected]+15) as start_time, (@b:[email protected]+15) as end_time 
     FROM `calls` 
     GROUP BY 
       cdr_id 
     ) as t 
WHERE c.duration BETWEEN t.start_time and t.end_time 
GROUP BY 
     t.start_time, t.end_time 
+0

Dies funktioniert, wenn Ihre Tabelle immer mehr als 5760 Zeilen enthält. – Quassnoi

+0

Obwohl dies funktionieren könnte, sollten Sie die Leistung im Vergleich zur Kouber-Methode überprüfen. Sie nehmen grundsätzlich einen prozeduralen Ansatz und wenden ihn in einer relationalen Datenbank an, die für satzbasierte Operationen erstellt wurde. –

3

die folgende Abfrage Ihren Bedürfnissen entspricht:

SELECT 
    (duration - duration % 15), 
    COUNT(*) 
FROM 
    call 
GROUP BY 
    (duration - duration % 15) 
ORDER BY 
    1; 

Sie können auch einige String-Formatierung, falls hinzufügen Sie müssen die Ausgabe genau so, wie Sie es beschrieben:

SELECT 
    (duration - duration % 15)::text || '-' || (duration - duration % 15 + 15)::text, 
    COUNT(*) 
FROM 
    call 
GROUP BY 
    (duration - duration % 15) 
ORDER BY 
    1;