SQL, max(Value), gruppiert über Zeitraum, mit zugehörigem Zeitpunkt

jan2001

Benutzer
Beiträge
7
Hallo,

ich sehe wahrscheinlich den Wald vor lauter Bäumen nicht.
Ich habe eine SQL-Tabelle mit Wetterdaten über einen Zeitraum mit jeweils 5-Minuten-Abständen.
Jeder Datensatz umfasst die gemessenen Werte sowie das entsprechende Datum mit Uhrzeit.
Ich möchte nun für einen bestimmten Zeitraum die Monats-Höchstwerte ermitteln.
Funktioniert soweit ganz gut - wie folgt:

---
SELECT max(fTempAussen), fDateTime from Vantage
where fDateTime>'2023-01-01'
GROUP BY date_format(fDateTime, '%Y-%m')
---

Allerdings möchte ich zusätzlich noch den entsprechenden Zeitpunkt des Messwertes ausgeben.
Hier komme ich einfach nicht weiter.

Hat jemand vielleicht einen Denkanstoss für mich?


Viele Grüße
Jan
 
Werbung:
Du gruppierst nach Jahr und Monat, naheliegend wäre, nach den gewünschten Zeitpunkt in die Formatmaske aufzunehmen. Aber das führt nicht zum Ziel.
Da Du (auch) nach Monat gruppierst, möchtest Du mehrere Peaks in einem Zeitabschnitt. Wäre es nur ein Wert, den Du suchst, könntest Du mit Order By und Limit arbeiten. Das hilft hier aber auch nicht.

Damit kommt man zum Standardfall bei group by Abfragen:
Gib mir irgendeinen anderen Wert aus dem Datensatz, der meine Aggregation betrifft.

An der Stelle gibt es keine Magie. Wenn Du die Maxima gefunden hast, musst Du sie mit den Originaldaten joinen, um andere Werte auszugeben, die Dich interessieren.
 
Die anderen Werte sind jedoch lediglich das Datum im Feld fDateTime, nach dem auch gruppiert wird.
Egal wie ich es bislang anstelle, bekomme ich kein Datum/Uhrzeit passend zum Messwert, da nach diesen bereits gruppiert wurde.

Hast du eventuell einen Syntax für mich?
 
Die anderen Werte sind jedoch lediglich das Datum im Feld fDateTime, nach dem auch gruppiert wird.
Äh ja?! Genau das habe ich geschrieben. Das ist DER Standard Fall bei Group By Abfragen, naja einer der Standardfälle:
Die Aggregat Operation liefert das Datum, das selbst wiederum der Schlüssel zu den anderen Feldern in dessen Datensatz sein soll.

Ich bin kein mySQL Freund. Ich habe Deine Tabellen und Deine Daten nicht. Du hast nicht sehr exakt beschrieben, was Du als Ergebnis haben möchtest und gar nicht, was Du schon versucht hast. Und was Du beschrieben hast, was "funktioniert", ist wahrscheinlich Zufall bzw. falsch. Du müsstest es also eher selbst hinbekommen und verstehen, was Du machen musst.

Punkt 1: Ich bezweifle, dass Dein gezeigtes Statement stimmt.
Man sollte nicht anders gruppieren, als man es ausgibt, außer man weiß genau was man tut:
Also statt Deinem Statement oben sollte es m.E. so lauten:
---
SELECT max(fTempAussen), date_format(fDateTime, '%Y-%m') from Vantage
where fDateTime>'2023-01-01'
GROUP BY date_format(fDateTime, '%Y-%m')
---
damit es korrekt ist. Ob dabei die Daten angezeigt werden, die Du haben willst, ist eine andere Frage.

So und jetzt schau Dir bitte noch mal genau an, was ich in meinem ersten Beitrag geschrieben habe und was dein Status Quo ist (ist nur eine Vermutung, da Deine Angaben unvollständig/falsch sind)
Du bekommst 2 Spalten, die z.B. so aussehen:
11.18|2023-01
12.32|2023-02
18.19|2023-03

Der "entsprechende Zeitpunkt", den Du nun auch noch haben möchtest, ist vermutlich zusätzlich der Tag und die Uhrzeit?

Du musst die Ausgabe deines jetzigen Statements mit den Originaldaten joinen, dann kannst Du Dir an Werten rausfischen, was Du möchtest.
Weißt Du, was ein Join ist?
 
Du musst die Ausgabe deines jetzigen Statements mit den Originaldaten joinen, dann kannst Du Dir an Werten rausfischen, was Du möchtest.
Weißt Du, was ein Join ist?
Nur im Groben, aus Access-VBA - jedoch weiß ich nicht, welche Art Join hier vonnöten ist und wie der entsprechende Syntax wäre.

Die Tabelle enthält natürlich auch ein Feld 'ID' - vermutlich ließe sich hierüber eine Verknüpfung realisieren.

Weitere Felder sind in dem Beispiel nicht nötigt, da der einzige Wert, den ich noch ermitteln will, der exakte Datum-Uhrzeit-Wert ist, der in eben diesen Feld steckt, nach dem auch gruppiert wurde.

Der "entsprechende Zeitpunkt", den Du nun auch noch haben möchtest, ist vermutlich zusätzlich der Tag und die Uhrzeit?
genau, so hatte ich es auch im ersten Beitrag geschrieben.


Wenn also jemand einen Tipp hat, wie ein solcher Join auszusehen hat, würde mich das sehr freuen.


Jan
 
Nachtrag:
alle Beispiele, die ich bisher zu Joins gefunden habe, banden zusätzliche Tabellen ein. Dies ist in meinem Fall nicht so, da das Feld DatumUhrzeit zweimal verwendet werden soll - einmal zum Gruppieren, einmal zum Ausgeben des jeweiligen, zugehörigen Wertes.

Ist in einer solchen Konstellation ein Join möglich?
 
Du hast nach der Aggregation ein Ergebniss. Dieses kannst Du als eigene Tabelle betrachten. Und dann hast Du ja noch die Ausgangstabelle.
Preisfrage: wie viele Tabellen hast Du nun?
 
Ich habe eine Tabelle.
In dieser einen Tabelle ist ein Feld ID (PK), ein Feld Messwert, ein Feld DatumUhrzeit.
Ich gruppiere die Daten nach Jahr-Monat und ermittle den Max-Wert für den Messwert.
Soweit komme ich.
Ich möchte zusätzlich zum aggregierten Messwert und dem gruppierten Datum (Jahr-Monat) noch den exakten Datum/Uhrzeit-Wert angeben.
Hierzu muss ich auf das Feld Datum/Uhrzeit zugreifen, welches ich aber bereits gruppiert habe.

Dazu benötige ich dann wohl einen Join. Ich kenne Joins jedoch nur aus Access-VBA, und dort zum Einbinden einer weiteren Tabelle - über einen PK. Mit ist nicht klar, ob/wie ich mit Joins auf ein und dieselbe Tabelle zugreifen kann.
 
Ist in einer solchen Konstellation ein Join möglich?
Du kannst joinen was Du willst.
Mit ist nicht klar, ob/wie ich mit Joins auf ein und dieselbe Tabelle zugreifen kann.
Ein Join hat technisch nichts mit PK zu tun, er wird allerdings sehr häufig genutzt, um PK und FK Spalten zu joinen.
SQL arbeitet mengenorientiert und Du definierst, was Du wie verknüpfen möchtest.
Eine Tabelle kann beliebig oft in einem Statement verwendet werden, ebenso wie ein komplettes SQL Statement. Dazu verwendet man einen Alias, der namentlich variiert, obwohl er u.U. die gleilche Tabelle anspricht.
Ebenso kann eine Alias für ein komplettes SQL Statement stehen.

schau mal hier:
 
Macht's doch nicht so spannend, wir posten doch sonst auch Code-Vorschläge als Antwort:
Code:
SELECT *
FROM (

SELECT max(fTempAussen) AS max_fTempAussen, date_format(fDateTime, '%Y-%m') AS format_fDateTime
from Vantage
where fDateTime>'2023-01-01'
GROUP BY date_format(fDateTime, '%Y-%m')

) t
LEFT JOIN Vantage v
ON t.format_fDateTime = date_format(v.fDateTime, '%Y-%m')
AND t.max_fTempAussen = v.fTempAussen
Das ist erstmal das grundsätzliche Prinzip das mittels Join umzusetzen. Du Aggregierst und joinst die echten Daten nochmal auf das Aggregat, dann hast du in t das Aggregat und und v liefert alle Spalten die dem zugrunde liegen. Das können auch mehrere Datensätze pro Aggregat sein wenn der Maximal Wert mehrfach eintritt.
 
@jan2001 - Von welchem Wert möchtest du das Datum & Uhrzeit ausgeben.
Minimal oder Maximal ?
Und was ist wenn es z.B mehrer gleiche Maximalwerte gibt ? Welches soll dann genommen werden ?

Gruß

Bernd
 
Werbung:
So gehts aber auch ohne JOIN


Code:
SELECT
  max(fTempAussen) fDateTime ,
  SUBSTRING_INDEX(GROUP_CONCAT(fDateTime ORDER BY fTempAussen),',',-1)
FROM Vantage
where fDateTime >'2023-01-01'
GROUP BY date_format(fDateTime, '%Y-%m');

Beispiel:


Code:
mysql> SELECT * from Vantage;
+----+---------------------+-------------+
| id | fDateTime           | fTempAussen |
+----+---------------------+-------------+
|  1 | 2023-01-01 12:00:00 |          21 |
|  2 | 2023-01-01 12:05:01 |        25.1 |
|  3 | 2023-01-01 13:07:12 |          18 |
|  4 | 2023-01-02 08:00:13 |        24.2 |
+----+---------------------+-------------+
4 rows in set (0.00 sec)

mysql> SELECT
    ->   max(fTempAussen) fDateTime ,
    ->   SUBSTRING_INDEX(GROUP_CONCAT(fDateTime ORDER BY fTempAussen),',',-1)
    -> FROM Vantage
    -> where fDateTime >'2023-01-01'
    -> GROUP BY date_format(fDateTime, '%Y-%m');
+-----------+----------------------------------------------------------------------+
| fDateTime | SUBSTRING_INDEX(GROUP_CONCAT(fDateTime ORDER BY fTempAussen),',',-1) |
+-----------+----------------------------------------------------------------------+
|      25.1 | 2023-01-01 12:05:01                                                  |
+-----------+----------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>
 
Zurück
Oben