sql >> Database teknologi >  >> RDS >> Mysql

Hvorfor returnerer MYSQL DB en beskadiget værdi, når der tages et gennemsnit over en Django models.DateTimeField?

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) .



  1. Regulære udtryk i SQL Server-servere?

  2. forespørgselsbygger:IN-klausul med sammensatte kolonner

  3. Download af data til en csv-fil fra MySQL ved hjælp af PHP

  4. MySQL-forespørgsel er langsommere efter oprettelse af indeks