Q1:Por que o banco de dados não retorna um valor válido para a média dessas duas datas?
R: O valor retornado é esperado, é um comportamento MySQL bem definido.
Manual de referência do MySQL:https://dev .mysql.com/doc/refman/5.5/en/date-and-time-types.html
No MySQL, o
AVG
função agregada opera em numérico valores. No MySQL, um
DATE
ou DATETIME
expressão pode ser avaliada em um numérico contexto. Como uma demonstração simples, realizando um numérico operação de adição em um
DATETIME
converte implicitamente o valor de data e hora em um número. Esta consulta: SELECT NOW(), NOW()+0
retorna um resultado como:
NOW() NOW()+0
------------------- -----------------------
2015-06-23 17:57:48 20150623175748.000000
Observe que o valor retornado para a expressão
NOW()+0
é não a DATETIME
, é um número . Quando você especifica um
SUM()
ou AVG()
função em um DATETIME
expressão, que é equivalente a converter o DATETIME
em um número e, em seguida, somar ou calcular a média do número. Ou seja, o retorno desta expressão
AVG(mydatetimecol)
é equivalente ao retorno desta expressão:AVG(mydatetimecol+0)
O que está sendo "média" é um valor numérico. E você observou, o valor retornado não é um datetime válido; e mesmo nos casos em que parece uma data e hora válida, provavelmente não é um valor que você consideraria uma verdadeira "média".
P2:como obtenho a média real desse campo se a maneira descrita falhar?
A2: Uma maneira de fazer isso é converter a data e hora em um valor numérico que pode ser calculado com "precisão" e, em seguida, convertê-lo novamente em uma data e hora.
Por exemplo, você pode converter a data e hora em um valor numérico representando um número de segundos de algum ponto fixo no tempo, e.
TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)
Você poderia então "fazer a média" desses valores, para obter uma média número de segundos a partir de um ponto fixo no tempo. (OBSERVAÇÃO:cuidado com a adição de um número extremamente grande de linhas, com valores extremamente grandes e excedendo o limite (valor numérico máximo), problemas de estouro numérico.)
AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date))
Para converter isso de volta para uma data e hora, adicione esse valor como um número de segundos de volta a um ponto fixo no tempo:
'2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND
(Observe que o
DATEIME
os valores são avaliados no fuso horário da sessão do MySQL; portanto, há casos extremos em que a configuração do time_zone
variável na sessão MySQL terá alguma influência no valor retornado.) O MySQL também fornece um
UNIX_TIMESTAMP()
função que retorna um valor inteiro no estilo unix, número de segundos desde o início da era (meia-noite de 1º de janeiro de 1970 UTC). Você pode usar isso para realizar a mesma operação de forma mais concisa: FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(t.my_date)))
Observe que essa expressão final está realmente fazendo a mesma coisa ... convertendo o valor de data e hora em um número de segundos desde '1970-01-01 00:00:00' UTC, obtendo uma média numérica disso e adicionando essa média número de segundos de volta para '1970-01-01' UTC e, finalmente, convertendo-o de volta para um
DATETIME
valor, representado na sessão atual time_zone
. Q3:O Django DateTimeField não está configurado para lidar com a média?
R: Aparentemente, os autores do Django estão satisfeitos com o valor retornado do banco de dados para uma expressão SQL
AVG(datetime)
.