sql >> Database >  >> RDS >> Mysql

Waarom retourneert MYSQL DB een beschadigde waarde bij het middelen over een Django-model.DateTimeField?

V1:Waarom retourneert de database geen geldige waarde voor het gemiddelde van deze twee datums?

A: De geretourneerde waarde wordt verwacht, het is goed gedefinieerd MySQL-gedrag.

MySQL-referentiehandleiding:https://dev .mysql.com/doc/refman/5.5/en/date-and-time-types.html

In MySQL is de AVG aggregatiefunctie werkt op numeriek waarden.

In MySQL, een DATE of DATETIME uitdrukking kan worden geëvalueerd in een numeriek context.

Als een eenvoudige demonstratie, het uitvoeren van een numerieke optelbewerking op een DATETIME converteert impliciet de datetime-waarde naar een getal. Deze vraag:

  SELECT NOW(), NOW()+0

geeft een resultaat als:

  NOW()                                NOW()+0  
  -------------------  -----------------------
  2015-06-23 17:57:48    20150623175748.000000

Merk op dat de waarde die wordt geretourneerd voor de uitdrukking NOW()+0 is niet een DATETIME , het is een nummer .

Wanneer u een SUM() . opgeeft of AVG() functie op een DATETIME expressie, dat komt overeen met het converteren van de DATETIME in een getal, en dan het getal optellen of middelen.

Dat wil zeggen, het resultaat van deze uitdrukking AVG(mydatetimecol) is gelijk aan het resultaat van deze uitdrukking:AVG(mydatetimecol+0)

Wat wordt "gemiddeld" is een numerieke waarde. En je hebt opgemerkt dat de geretourneerde waarde geen geldige datetime is; en zelfs in gevallen waarin het lijkt op een geldige datetime, is het waarschijnlijk geen waarde die u als een echt "gemiddelde" zou beschouwen.

V2:Hoe krijg ik het werkelijke gemiddelde van dit veld als de beschreven manier niet werkt?

A2: Een manier om dat te doen is door de datetime om te zetten in een numerieke waarde die "nauwkeurig" kan worden gemiddeld, en die vervolgens terug te converteren naar een datetime.

U kunt bijvoorbeeld de datetime omzetten in een numerieke waarde die een aantal seconden vertegenwoordigt vanaf een vast tijdstip, bijv.

  TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)

U kunt die waarden dan "gemiddelden" om een ​​gemiddeld aantal seconden te krijgen vanaf een vast tijdstip. (OPMERKING:pas op voor het optellen van een extreem groot aantal rijen, met extreem grote waarden, en het overschrijden van de limiet (maximale numerieke waarde), problemen met numerieke overloop.)

  AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date))

Om dat terug te zetten naar een datetime, voegt u die waarde toe als een aantal seconden terug naar een vast tijdstip:

  '2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND

(Merk op dat de DATEIME waarden worden geëvalueerd in de tijdzone van de MySQL-sessie; dus er zijn randgevallen waarbij de instelling van de time_zone variabele in de MySQL-sessie zal enige invloed hebben op de geretourneerde waarde.)

MySQL biedt ook een UNIX_TIMESTAMP() functie die een geheel getal in Unix-stijl retourneert, het aantal seconden vanaf het begin van het tijdperk (middernacht 1 januari 1970 UTC). U kunt dat gebruiken om dezelfde bewerking beknopter uit te voeren:

  FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(t.my_date)))

Merk op dat deze laatste uitdrukking in feite hetzelfde doet... de datetime-waarde converteren naar een aantal seconden sinds '1970-01-01 00:00:00' UTC, daarvan een numeriek gemiddelde nemen en dat gemiddelde dan optellen aantal seconden terug naar '1970-01-01' UTC, en dat uiteindelijk terug converteren naar een DATETIME waarde, weergegeven in de huidige sessie time_zone .

Q3:Is Django DateTimeField niet ingesteld om middeling af te handelen?

A: Blijkbaar zijn de auteurs van Django tevreden met de waarde die uit de database wordt geretourneerd voor een SQL-expressie AVG(datetime) .



  1. Hoe krijg je de som voor elke afzonderlijke waarde in een andere kolom?

  2. Hoe mysql workbench te verbinden met mysql in docker?

  3. Hoe krijg je meerdere tellingen met één SQL-query?

  4. Is de VARCHAR-limiet van belang?