Spørgsmål 1:Hvorfor returnerer databasen ikke en gyldig værdi for gennemsnittet af disse to datoer?
A: Den returnerede værdi forventes, det er veldefineret MySQL-adfærd.
MySQL Reference Manual:https://dev .mysql.com/doc/refman/5.5/en/date-and-time-types.html
I MySQL er AVG
aggregeret funktion fungerer på numerisk værdier.
I MySQL, en DATE
eller DATETIME
udtryk kan evalueres i et numerisk kontekst.
Som en simpel demonstration udfører du en numerisk tilføjelsesoperation på en DATETIME
konverterer implicit datetime-værdien til et tal. Denne forespørgsel:
SELECT NOW(), NOW()+0
returnerer et resultat som:
NOW() NOW()+0
------------------- -----------------------
2015-06-23 17:57:48 20150623175748.000000
Bemærk, at værdien returneret for udtrykket NOW()+0
er ikke en DATETIME
, det er et nummer .
Når du angiver en SUM()
eller AVG()
funktion på en DATETIME
udtryk, det svarer til at konvertere DATETIME
ind i et tal, og summer eller gennemsnit af tallet.
Det vil sige returneringen fra dette udtryk AVG(mydatetimecol)
svarer til returneringen fra dette udtryk:AVG(mydatetimecol+0)
Hvad der "gennemsnittes" er en numerisk værdi. Og du har observeret, at den returnerede værdi ikke er et gyldigt datetime; og selv i tilfælde, hvor det tilfældigvis ligner et gyldigt dato og klokkeslæt, er det sandsynligvis ikke en værdi, du ville betragte som et sandt "gennemsnit".
Spørgsmål 2:Hvordan får jeg det faktiske gennemsnit af dette felt, hvis den beskrevne måde mislykkes?
A2: En måde at gøre det på er at konvertere dato-klokkeslættet til en numerisk værdi, der kan beregnes "nøjagtigt" i gennemsnit, og derefter konvertere det tilbage til et dato-klokkeslæt.
For eksempel kan du konvertere datetime til en numerisk værdi, der repræsenterer et antal sekunder fra et bestemt tidspunkt, f.eks.
TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)
Du kan derefter "gennemsnitte" disse værdier for at få et gennemsnitligt antal sekunder fra et fast tidspunkt. (BEMÆRK:pas på med at lægge et ekstremt stort antal rækker sammen med ekstremt store værdier og overskride grænsen (maksimal numerisk værdi), numeriske overløbsproblemer.)
AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date))
For at konvertere det tilbage til en dato og klokkeslæt skal du tilføje denne værdi som et antal sekunder tilbage til det faste tidspunkt:
'2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND
(Bemærk, at DATEIME
værdier evalueres i tidszonen for MySQL-sessionen; så der er kanttilfælde, hvor indstillingen af time_zone
variabel i MySQL-sessionen vil have en vis indflydelse på den returnerede værdi.)
MySQL giver også en UNIX_TIMESTAMP()
funktion, som returnerer en heltalsværdi i unix-stil, antal sekunder fra begyndelsen af æraen (midnat 1. januar 1970 UTC). Du kan bruge det til at udføre den samme handling mere kortfattet:
FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(t.my_date)))
Bemærk, at dette endelige udtryk i virkeligheden gør det samme... konverterer datetime-værdien til et antal sekunder siden '1970-01-01 00:00:00' UTC, tager et numerisk gennemsnit af det, og tilføjer derefter dette gennemsnit antal sekunder tilbage til '1970-01-01' UTC, og til sidst konvertere det tilbage til en DATETIME
værdi, repræsenteret i den aktuelle session time_zone
.
Spørgsmål 3:Er Django DateTimeField ikke konfigureret til at håndtere gennemsnitsberegning?
A: Tilsyneladende er forfatterne af Django tilfredse med den værdi, der returneres fra databasen for et SQL-udtryk AVG(datetime)
.