Q1:データベースがこれら2つの日付の平均に対して有効な値を返さないのはなぜですか?
A: 返される値は予期されたものであり、明確に定義されたMySQLの動作です。
MySQLリファレンスマニュアル: https:// dev .mysql.com / doc / refman / 5.5 / en / date-and-time-types.html
MySQLでは、 AVG
集計関数は数値で動作します 値。
MySQLでは、 DATE
またはDATETIME
式は数値で評価できます コンテキスト。
簡単なデモンストレーションとして、数値を実行します DATETIME
での加算演算 日時の値を暗黙的に数値に変換します。このクエリ:
SELECT NOW(), NOW()+0
次のような結果を返します:
NOW() NOW()+0
------------------- -----------------------
2015-06-23 17:57:48 20150623175748.000000
式NOW()+0
に対して返される値に注意してください。 ではありません DATETIME
、それは番号 。
SUM()
を指定する場合 またはAVG()
DATETIME
で機能する 式、これはDATETIME
を変換するのと同じです 数値に変換してから、数値を合計または平均化します。
つまり、この式からの戻り値AVG(mydatetimecol)
次の式からの戻り値と同等です:AVG(mydatetimecol+0)
「平均化」されているのは数値です。そして、あなたが観察したように、返される値は有効な日時ではありません。また、有効な日時のように見える場合でも、真の「平均」と見なす値ではない可能性があります。
Q2:説明されている方法が失敗した場合、このフィールドの実際の平均を取得するにはどうすればよいですか?
A2: そのための1つの方法は、日時を「正確に」平均化できる数値に変換してから、それを日時に戻すことです。
たとえば、日時を秒数を表す数値に変換できます。 ある固定された時点から、例えば
TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)
次に、これらの値を「平均化」して、平均秒数を取得できます。 一定の時点から。 (注:非常に多くの行を合計し、値が非常に大きく、制限(最大数値)を超えると、数値オーバーフローの問題が発生することに注意してください。)
AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date))
これを日時に戻すには、その値を秒数として追加します。 固定された時点に戻る:
'2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND
(DATEIME
に注意してください 値はMySQLセッションのタイムゾーンで評価されます。そのため、time_zone
の設定がエッジケースになります。 MySQLセッションの変数は、返される値に何らかの影響を及ぼします。)
MySQLはUNIX_TIMESTAMP()
も提供します 時代の始まり(1970年1月1日深夜UTC)からの秒数であるUNIXスタイルの整数値を返す関数。これを使用して、同じ操作をより簡潔に実行できます。
FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(t.my_date)))
この最後の式は実際には同じことをしていることに注意してください...日時値を「1970-01-0100:00:00」UTCからの秒数に変換し、その数値平均を取り、その平均を加算します'1970-01-01' UTCに戻って、最後にそれをDATETIME
に変換して戻す秒数 現在のセッションで表される値time_zone
。
Q3:Django DateTimeFieldは、平均化を処理するように設定されていませんか?
A: どうやら、Djangoの作者は、SQL式 AVG(datetime)
のデータベースから返された値に満足しているようです。 。