F1:Warum gibt die Datenbank keinen gültigen Wert für den Durchschnitt dieser beiden Daten zurück?
A: Der zurückgegebene Wert wird erwartet, es ist wohldefiniertes MySQL-Verhalten.
MySQL-Referenzhandbuch:https://dev .mysql.com/doc/refman/5.5/en/date-and-time-types.html
In MySQL der AVG
Aggregatfunktion arbeitet mit numerischen Werte.
In MySQL ein DATE
oder DATETIME
Ausdruck kann in einem numeric ausgewertet werden Kontext.
Als einfache Demonstration eine numerische ausführen Additionsoperation an einem DATETIME
wandelt den datetime-Wert implizit in eine Zahl um. Diese Abfrage:
SELECT NOW(), NOW()+0
gibt ein Ergebnis zurück wie:
NOW() NOW()+0
------------------- -----------------------
2015-06-23 17:57:48 20150623175748.000000
Beachten Sie, dass der für den Ausdruck zurückgegebene Wert NOW()+0
ist ist nicht a DATETIME
, es ist eine Zahl .
Wenn Sie eine SUM()
angeben oder AVG()
Funktion an einem DATETIME
Ausdruck, das entspricht der Konvertierung von DATETIME
in eine Zahl umwandeln und dann die Zahl summieren oder mitteln.
Das heißt, die Rückgabe dieses Ausdrucks AVG(mydatetimecol)
entspricht der Rückgabe dieses Ausdrucks:AVG(mydatetimecol+0)
Was "gemittelt" wird, ist ein numerischer Wert. Und Sie haben festgestellt, dass der zurückgegebene Wert keine gültige Datumszeit ist; und selbst in Fällen, in denen es wie eine gültige Datumszeit aussieht, ist es wahrscheinlich kein Wert, den Sie als echten "Durchschnitt" betrachten würden.
F2:Wie erhalte ich den tatsächlichen Durchschnitt dieses Felds, wenn der beschriebene Weg fehlschlägt?
A2: Eine Möglichkeit, dies zu tun, besteht darin, die Datumszeit in einen numerischen Wert umzuwandeln, der "genau" gemittelt werden kann, und diesen dann wieder in eine Datumszeit umzuwandeln.
Beispielsweise könnten Sie datetime in einen numerischen Wert umwandeln, der eine Anzahl von Sekunden darstellt von einem festen Zeitpunkt, z.B.
TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)
Sie können diese Werte dann "mitteln", um eine durchschnittliche Anzahl von Sekunden zu erhalten ab einem festen Zeitpunkt. (HINWEIS:Achten Sie darauf, eine extrem große Anzahl von Zeilen mit extrem großen Werten zu addieren und das Limit zu überschreiten (maximaler numerischer Wert), numerische Überlaufprobleme.)
AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date))
Um dies wieder in eine Datumszeit umzuwandeln, fügen Sie diesen Wert als Anzahl von Sekunden hinzu zurück zu einem festen Zeitpunkt:
'2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND
(Beachten Sie, dass die DATEIME
Werte werden in der Zeitzone der MySQL-Session ausgewertet; Es gibt also Grenzfälle, in denen die Einstellung der time_zone
Variable in der MySQL-Session hat einen gewissen Einfluss auf den zurückgegebenen Wert.)
MySQL bietet auch einen UNIX_TIMESTAMP()
Funktion, die einen ganzzahligen Wert im Unix-Stil zurückgibt, die Anzahl der Sekunden seit Beginn der Ära (Mitternacht des 1. Januar 1970 UTC). Sie können dies verwenden, um dieselbe Operation präziser auszuführen:
FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(t.my_date)))
Beachten Sie, dass dieser letzte Ausdruck wirklich das Gleiche tut ... den datetime-Wert in eine Anzahl von Sekunden seit '1970-01-01 00:00:00' UTC umwandelt, einen numerischen Durchschnitt davon nimmt und diesen Durchschnitt dann addiert Anzahl der Sekunden zurück auf '1970-01-01' UTC und wandelt diese schließlich zurück in ein DATETIME
Wert, dargestellt in der aktuellen Sitzung time_zone
.
F3:Ist Django DateTimeField nicht für die Mittelwertbildung eingerichtet?
A: Anscheinend sind die Autoren von Django zufrieden mit dem Wert, der von der Datenbank für einen SQL-Ausdruck AVG(datetime)
zurückgegeben wird .