T1:Mengapa basis data tidak mengembalikan nilai yang valid untuk rata-rata dua tanggal ini?
J: Nilai yang dikembalikan diharapkan, itu adalah perilaku MySQL yang terdefinisi dengan baik.
Manual Referensi MySQL:https://dev .mysql.com/doc/refman/5.5/en/date-and-time-types.html
Di MySQL, AVG
fungsi agregat beroperasi pada numerik nilai.
Di MySQL, DATE
atau DATETIME
ekspresi dapat dievaluasi dalam numerik konteks.
Sebagai demonstrasi sederhana, melakukan numerik operasi penambahan pada DATETIME
secara implisit mengubah nilai datetime menjadi angka. Kueri ini:
SELECT NOW(), NOW()+0
mengembalikan hasil seperti:
NOW() NOW()+0
------------------- -----------------------
2015-06-23 17:57:48 20150623175748.000000
Perhatikan bahwa nilai yang dikembalikan untuk ekspresi NOW()+0
adalah tidak a DATETIME
, itu adalah angka .
Saat Anda menentukan SUM()
atau AVG()
berfungsi pada DATETIME
ekspresi, itu setara dengan mengonversi DATETIME
menjadi angka, lalu menjumlahkan atau merata-ratakan angka tersebut.
Artinya, pengembalian dari ekspresi ini AVG(mydatetimecol)
setara dengan pengembalian dari ekspresi ini:AVG(mydatetimecol+0)
Apa yang "rata-rata" adalah nilai numerik. Dan Anda telah mengamati, nilai yang dikembalikan bukan waktu yang valid; dan bahkan dalam kasus di mana itu terlihat seperti waktu yang valid, kemungkinan itu bukan nilai yang Anda anggap sebagai "rata-rata" yang sebenarnya.
Q2:Bagaimana cara mendapatkan rata-rata sebenarnya dari bidang ini jika cara yang dijelaskan gagal?
A2: Salah satu cara untuk melakukannya adalah dengan mengonversi datetime menjadi nilai numerik yang dapat dirata-ratakan "secara akurat", lalu mengonversinya kembali menjadi datetime.
Misalnya, Anda dapat mengonversi datetime menjadi nilai numerik yang mewakili jumlah detik dari beberapa titik waktu tertentu, mis.
TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)
Anda kemudian dapat "rata-rata" nilai tersebut, untuk mendapatkan rata-rata jumlah detik dari titik waktu yang tetap. (CATATAN:berhati-hatilah agar tidak menambahkan jumlah baris yang sangat besar, dengan nilai yang sangat besar, dan melebihi batas (nilai numerik maksimum), masalah luapan numerik.)
AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date))
Untuk mengonversinya kembali ke waktu tanggal, tambahkan nilai itu sebagai jumlah detik kembali ke titik waktu yang tetap:
'2015-01-01' + INTERVAL AVG(TIMESTAMPDIFF(SECOND,'2015-01-01',t.my_date)) SECOND
(Perhatikan bahwa DATEIME
nilai dievaluasi dalam zona waktu sesi MySQL; jadi ada kasus tepi di mana pengaturan time_zone
variabel dalam sesi MySQL akan memiliki pengaruh pada nilai yang dikembalikan.)
MySQL juga menyediakan UNIX_TIMESTAMP()
fungsi yang mengembalikan nilai integer gaya unix, jumlah detik dari awal era (tengah malam 1 Januari 1970 UTC). Anda dapat menggunakannya untuk menyelesaikan operasi yang sama dengan lebih ringkas:
FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(t.my_date)))
Perhatikan bahwa ekspresi terakhir ini benar-benar melakukan hal yang sama... mengubah nilai datetime menjadi beberapa detik sejak '1970-01-01 00:00:00' UTC, mengambil rata-rata numerik dari itu, dan kemudian menambahkan rata-rata itu jumlah detik kembali ke '1970-01-01' UTC, dan akhirnya mengonversinya kembali ke DATETIME
nilai, diwakili dalam time_zone
sesi saat ini .
Q3:Apakah Django DateTimeField tidak disetel untuk menangani rata-rata?
J: Tampaknya, penulis Django puas dengan nilai yang dikembalikan dari database untuk ekspresi SQL AVG(datetime)
.