Granularität in Query festlegen

knabnetaD

Benutzer
Beiträge
12
Hallo zusammen,
ich habe folgende Query:
Code:
SELECT id1, fk_id, daten
FROM table1
WHERE EXISTS (SELECT id2
                  FROM table2
                  WHERE table2.id2 = table1.fk_id
AND (NOT EXISTS (SELECT id3
                    FROM table3
                    WHERE table3.id3 = table1.id1)
AND NOT EXISTS (SELECT id4
                    FROM table4
                    WHERE table4.id4 = table1.id1)))

Was macht die Query?
Ich habe in table1 jede Menge Zustandsdaten wie CPU-Auslastung, Ping, etc. In table2 wird definiert welche Zustandsdaten ich haben will. Wenn diese Zustandsdaten noch nicht in table3 und table4 vorhanden sind, werden sie als Ergebnis zurück gegeben.

Jetzt ist es so, dass z.B. der Ping jede Minute ausgeführt und das Ergebnis in der DB gespeichert wird.
Wie kann ich die Query jetzt so ändern, dass ich eine Granularität festlegen kann?

D.h. ich möchte z.B. sagen, dass ich die Pingzeiten über 30 Minuten aggregiert haben will.
D.h. Aus 30 Ping-Zeiten wird der Mittelwert berechnet und dieser wird dann als Ergebnis zurück geliefert.

Wäre super wenn mir jemand helfen kann.
Da gibt es doch mit Sicherheit eine Funktion für, oder?
Kann aber leider nichts finden, was mir weiterhelfen würde.

VIELEN DANK!
 
Werbung:
Ich sehe in SQL keine Möglichkeit sowas wie eine Gruppierung zu Durchschnittsmengen einfach umzusetzen. Die meisten Ansätze dazu beziehen sich auf irgendwas wie Datum, Monat oder Produktkategorie, so das nicht immer 30 Datensätze sondern alle Daten eines bestimmten Tages zusammen gefasst werden. Du müsstest also entweder anhand eines Datetime Feldes für fixe halbe Stunden Intervalle den Durchschnitt berechnen oder die Datensätze durchnummerieren und dich darauf beziehen. Eventuell wäre aber auch ein gleitender Mittelwert was für dich, ähnlich dem hier:
http://www.office-loesung.de/ftopic229035_0_0_asc.php
 
Eine Datetime-Spalte ist vorhanden.

Diese Zeiten sind aber nicht fix, da die Erhebung der Daten je nach Auslastung statt findet.
Also der erste Wert könnte dann um 10:15 kommen, der zweite um 10:17, der dritte um 11:01 usw.

Wie würde eine Aggregation über 60 Minuten dann in der Query aussehen?
Code:
select ...
from ...
where ...
group by datetime between time and time+60

Allerdings müsste time dann nach jedem Schritt um 60 Minuten erhöht werden, oder?

Code:
vDatetime = 01-01-2012-10-10-00;
 
select ...
from ...
where ...
group by datetime between vDatetime and vDatetime +60;
 
vDatetime + 60 Minuten;

so?
 
In etwa so:
Code:
SELECT    avg(len(FIRMA)) AS zahl,
        datepart(yyyy,LASTDAT) * 1000000 +
        datepart(mm,LASTDAT) * 10000 +
        datepart(dd,LASTDAT) * 100 +
        datepart(hh,LASTDAT) AS Zeitraum
FROM    ADRESSEN
WHERE    LASTDAT IS NOT NULL
GROUP BY datepart(yyyy,LASTDAT) * 1000000 +
        datepart(mm,LASTDAT) * 10000 +
        datepart(dd,LASTDAT) * 100 +
        datepart(hh,LASTDAT)
ORDER BY datepart(yyyy,LASTDAT) * 1000000 +
        datepart(mm,LASTDAT) * 10000 +
        datepart(dd,LASTDAT) * 100 +
        datepart(hh,LASTDAT)
Das ist eine Tabelle mit Unternehmensbezeichnungen wo ich die len(FIRMA) einfach mal als Grundlage für einen Zahlenwert genommen habe und das letzte Bearbeitungsdatum auf Jahr,Monat,Tag,Stunde runter gebrochen habe. Das kriegt man defninitiv noch schöner hin, ist aber erstmal nur zum testen.
 
PS: Du solltest dir aber auf jedenfall mal die Variante mit einem gleitenden Mittelwert angucken. Das scheint mir die interessantere Methode um z.B. Pingzeiten zu überwachen.
 
Werbung:
Hallo,
diese Fragestellung hat mich an ein altes Projekt erinnert. Ich sollte die Daten einer Telefonanlage auswerten, wobei die Anzahl der eingegangenen Anrufe über einen Zeitinterval zusammengefasst werden sollten. Dieser Zeitintervall sollte natürlich variabel sein.
Ich habe mich dann einer einfachen mathematischen Funktion bedient. Um das zu veranschaulichen habe ich mal ein kleines Beispiel zusammengestrickt, das allerdings auf dem MS SQL Server entworfen ist. Die mathematische Funktion sollte es unter MySQL aber auch geben. Wichtig ist ja prinzipiell die Idee, wie es funktionieren könnte.

Code:
CREATE TABLE #a
( Nr int IDENTITY(1,1),
       Typ varchar(255),
       [System] varchar(255),
       Eingang datetime,
       Wert float
)
 
DECLARE @Start datetime, @Interval_Min int
SET @Start=DATEADD(hour, -33, GETDATE())
SET @Interval_Min=60
DECLARE @Eingang datetime = @Start
 
WHILE CONVERT(varchar(10), @Start, 112)=CONVERT(varchar(10), @Eingang, 112)
BEGIN
     INSERT INTO #a (Typ, [System], Eingang, Wert) VALUES ('ping', 'MachineA', @Eingang, RAND()*100+40)
     SET @Eingang = DATEADD(second, RAND()*480+10, @Eingang)
END
 
SELECT Typ, System, MIN(Eingang) as Interval_Start, MAX(Eingang) as Interval_Ende,
AVG(Wert) as AVG_Wert,
COUNT(Nr) as Anzahl_Eingänge,
FLOOR(CAST(DATEDIFF(minute, @Start, Eingang) as float) / CAST(@Interval_Min as float)) as Lfd_Interval
FROM #a
GROUP BY Typ, System,
FLOOR(CAST(DATEDIFF(minute, @Start, Eingang) as float) / CAST(@Interval_Min as float))
 
DROP TABLE #a

Interessant für die Frage ist eigentlich erst das Select. Die Tabelle im Beispiel sind nur generierte Daten, wie ich sie mir in deiner Tabelle vorstelle.
Im Select erfolgt die Gruppierung über eine mathematische Funktion (FLOOR). Diese ist so ausgelegt, dass die Dateneingänge durch einen mit Parameter (@Interval_Min) festgelegten Wert zu Minuten-Blöcken zusammengefasst werden. Benötigt wird halt nur ein Start-Parameter, der den Startzeitpunkt der Auswertung angibt. Einen Parameter für das Auswertungs-Ende ist im Beispiel jetzt nicht vorgesehen, läßt sich aber ja ohne weiteres einbauen.

Viele Grüße,
Tommi
 
Zurück
Oben