Ich habe eine Tabelle mit Sensordaten. Jede Zeile hat eine Sensor-ID, einen Zeitstempel und andere Felder. Ich möchte für jeden Sensor eine einzelne Zeile mit dem neuesten Zeitstempel auswählen, einschließlich einiger anderer Felder.
Ich dachte, dass die Lösung darin bestehen würde, nach Sensor-ID zu gruppieren und dann nach max (Zeitstempel) zu sortieren, wie folgt:
SELECT sensorID,timestamp,sensorField1,sensorField2
FROM sensorTable
GROUP BY sensorID
ORDER BY max(timestamp);
Dies gibt mir einen Fehler, der besagt, dass "sensorField1 in der group by-Klausel erscheinen oder in einem Aggregat verwendet werden muss".
Was ist der richtige Weg, um dieses Problem anzugehen?
sql
greatest-n-per-group
ehrlich gesagt
quelle
quelle
Antworten:
Der Vollständigkeit halber ist hier eine andere mögliche Lösung:
SELECT sensorID,timestamp,sensorField1,sensorField2 FROM sensorTable s1 WHERE timestamp = (SELECT MAX(timestamp) FROM sensorTable s2 WHERE s1.sensorID = s2.sensorID) ORDER BY sensorID, timestamp;
Ich denke, es ist ziemlich selbsterklärend, aber wenn Sie möchten, finden Sie hier weitere Informationen sowie weitere Beispiele. Es stammt aus dem MySQL-Handbuch, aber die obige Abfrage funktioniert mit jedem RDBMS (Implementierung des SQL'92-Standards).
quelle
Dies kann auf relativ elegante Weise
SELECT DISTINCT
wie folgt erfolgen:SELECT DISTINCT ON (sensorID) sensorID, timestamp, sensorField1, sensorField2 FROM sensorTable ORDER BY sensorID, timestamp DESC;
Das obige funktioniert für PostgreSQL (einige weitere Informationen hier ), aber ich denke auch andere Engines. Falls dies nicht offensichtlich ist, sortieren Sie die Tabelle nach Sensor-ID und Zeitstempel (vom neuesten zum ältesten) und geben dann die erste Zeile (dh den neuesten Zeitstempel) für jede eindeutige Sensor-ID zurück.
In meinem Anwendungsfall habe ich ~ 10 Millionen Messwerte von ~ 1K-Sensoren, daher ist der Versuch, die Tabelle mit einem zeitstempelbasierten Filter mit sich selbst zu verbinden, sehr ressourcenintensiv. Das oben genannte dauert einige Sekunden.
quelle
Sie können die Tabelle mit sich selbst verbinden (auf Sensor-ID) und
left.timestamp < right.timestamp
als Verknüpfungsbedingung hinzufügen . Dann wählen Sie die Zeilen aus, woright.id
istnull
. Voila, du hast den neuesten Eintrag pro Sensor.http://sqlfiddle.com/#!9/45147/37
SELECT L.* FROM sensorTable L LEFT JOIN sensorTable R ON L.sensorID = R.sensorID AND L.timestamp < R.timestamp WHERE isnull (R.sensorID)
Beachten Sie jedoch, dass dies sehr ressourcenintensiv ist, wenn Sie eine kleine Anzahl von IDs und viele Werte haben! Daher würde ich dies nicht für eine Art Messgerät empfehlen, bei dem jeder Sensor jede Minute einen Wert erfasst. In einem Anwendungsfall, in dem Sie "Revisionen" von etwas verfolgen müssen, das sich nur "manchmal" ändert, ist dies jedoch einfach.
quelle
Sie können nur Spalten auswählen, die sich in der Gruppe befinden oder in einer Aggregatfunktion verwendet werden. Sie können einen Join verwenden, um dies zum Laufen zu bringen
select s1.* from sensorTable s1 inner join ( SELECT sensorID, max(timestamp) as mts FROM sensorTable GROUP BY sensorID ) s2 on s2.sensorID = s1.sensorID and s1.timestamp = s2.mts
quelle
select * from sensorTable where (sensorID, timestamp) in (select sensorID, max(timestamp) from sensorTable group by sensorID)
.WITH SensorTimes As ( SELECT sensorID, MAX(timestamp) "LastReading" FROM sensorTable GROUP BY sensorID ) SELECT s.sensorID,s.timestamp,s.sensorField1,s.sensorField2 FROM sensorTable s INNER JOIN SensorTimes t on s.sensorID = t.sensorID and s.timestamp = t.LastReading
quelle
Es gibt eine allgemeine Antwort, die ich hier noch nicht gesehen habe, nämlich die Fensterfunktion. Es ist eine Alternative zur korrelierten Unterabfrage, wenn Ihre Datenbank dies unterstützt.
SELECT sensorID,timestamp,sensorField1,sensorField2 FROM ( SELECT sensorID,timestamp,sensorField1,sensorField2 , ROW_NUMBER() OVER( PARTITION BY sensorID ORDER BY timestamp ) AS rn FROM sensorTable s1 WHERE rn = 1 ORDER BY sensorID, timestamp;
Ich verwende dies tatsächlich mehr als korrelierte Unterabfragen. Fühlen Sie sich frei, mich in den Kommentaren über die Effizienz zu überfallen, ich bin mir nicht sicher, wie es sich in dieser Hinsicht stapelt.
quelle
Ich hatte größtenteils das gleiche Problem und fand eine andere Lösung, die es einfach macht, diese Art von Problem abzufragen.
Ich habe eine Tabelle mit Sensordaten (1-Minuten-Daten von ca. 30 Sensoren)
und ich habe eine Sensortabelle, die viele meist statische Informationen über den Sensor enthält, aber die relevanten Felder sind folgende:
Das tvLastupdate und das tvLastValue werden bei Einfügungen in die SensorReadings-Tabelle in einem Trigger festgelegt. Ich habe immer direkten Zugriff auf diese Werte, ohne teure Abfragen durchführen zu müssen. Dies denormalisiert leicht. Die Abfrage ist trivial:
SELECT idSensor,Description,tvLastUpdate,tvLastValue FROM Sensors
Ich verwende diese Methode für Daten, die häufig abgefragt werden. In meinem Fall habe ich eine Sensortabelle und eine große Ereignistabelle, in der Daten auf Minutenebene eingehen, UND Dutzende von Maschinen aktualisieren Dashboards und Diagramme mit diesen Daten. In meinem Datenszenario funktioniert die Trigger-and-Cache-Methode gut.
quelle