Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Warum gibt MYSQL DB einen beschädigten Wert zurück, wenn über ein Django-Models.DateTimeField gemittelt wird?

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 .