Saya sedang membangun sistem acara khusus, dan jika Anda memiliki acara berulang yang terlihat seperti ini:
Event A berulang setiap 4 hari mulai tanggal 3 Maret 2011
atau
Acara B berulang setiap 2 minggu pada hari Selasa mulai tanggal 1 Maret 2011
Bagaimana saya bisa menyimpannya dalam Database dengan cara yang akan memudahkan pencarian. Saya tidak ingin masalah kinerja jika ada sejumlah besar acara, dan saya harus membahas masing-masing dan setiap saat membuat kalender.
database-design
calendar
Brandon Wamboldt
sumber
sumber
1299132000
hardcoded? Apa yang akan dilakukan jika saya perlu mendapatkan tanggal dan pengguna untuk tanggal akhir tertentu?Jawaban:
Menyimpan Pola Pengulangan "Sederhana"
Untuk kalender berbasis PHP / MySQL saya, saya ingin menyimpan informasi acara berulang / berulang seefisien mungkin. Saya tidak ingin memiliki banyak baris, dan saya ingin dengan mudah mencari semua acara yang akan berlangsung pada tanggal tertentu.
Metode di bawah ini adalah besar di menyimpan mengulangi informasi yang terjadi secara berkala, misalnya setiap hari, setiap n hari, setiap minggu, setiap bulan setiap tahun, dll dll Ini termasuk setiap Selasa dan Kamis jenis pola juga, karena mereka disimpan secara terpisah setiap minggu dimulai pada hari Selasa dan setiap minggu dimulai pada hari Kamis.
Dengan asumsi saya punya dua tabel, yang disebut
events
seperti ini:Dan sebuah tabel bernama
events_meta
seperti ini:Dengan repeat_start menjadi tanggal tanpa waktu sebagai cap waktu unix, dan repeat_interval jumlah dalam detik antar interval (432000 adalah 5 hari).
repeat_interval_1 berjalan dengan repeat_start dari ID 1. Jadi jika saya memiliki acara yang berulang setiap hari Selasa dan setiap hari Kamis, repeat_interval akan menjadi 604800 (7 hari), dan akan ada 2 repeat_start dan 2 repeat_intervals. Tabelnya akan terlihat seperti ini:
Kemudian, jika Anda memiliki kalender yang berulang setiap hari, mengambil acara untuk hari itu, kueri akan terlihat seperti ini:
Mengganti
{current_timestamp}
dengan cap waktu unix untuk tanggal saat ini (Mengurangi waktu, sehingga nilai jam, menit dan kedua akan ditetapkan ke 0).Semoga ini akan membantu orang lain juga!
Menyimpan Pola Pengulangan "Kompleks"
Metode ini lebih cocok untuk menyimpan pola yang kompleks seperti
Event A repeats every month on the 3rd of the month starting on March 3, 2011
atau
Event A repeats Friday of the 2nd week of the month starting on March 11, 2011
Saya akan merekomendasikan menggabungkan ini dengan sistem di atas untuk fleksibilitas paling. Tabel untuk ini harus seperti:
Dan sebuah tabel bernama
events_meta
seperti ini:repeat_week_im
mewakili minggu pada bulan berjalan, yang bisa berpotensi antara 1 dan 5.repeat_weekday
di hari minggu, 1-7.Sekarang dengan asumsi Anda mengulangi hari / minggu untuk membuat tampilan bulan di kalender Anda, Anda dapat membuat kueri seperti ini:
Ini dikombinasikan dengan metode di atas dapat dikombinasikan untuk mencakup sebagian besar pola peristiwa berulang / berulang. Jika saya melewatkan sesuatu, silakan tinggalkan komentar.
sumber
AND ( ( CASE ( 1299132000 - EM1.meta_value ) WHEN 0 THEN 1 ELSE ( 1299132000 - EM1.meta_value) END ) / EM2.meta_value ) = 1
adalah ini/ EM2.meta_value
ditempatkan salah?86400
detik dalam sehari, karena itu tidak memperhitungkan waktu musim panas. Lebih tepat untuk menghitung hal-hal ini secara dinamis dengan cepat dan bukannya menyimpaninterval = daily
daninterval_count = 1
atauinterval = monthly
daninterval_count = 1
.Sementara jawaban yang diterima saat ini sangat membantu saya, saya ingin berbagi beberapa modifikasi berguna yang menyederhanakan pertanyaan dan juga meningkatkan kinerja.
Acara Ulangi "Sederhana"
Untuk menangani acara yang berulang secara berkala, seperti:
atau
Anda harus membuat dua tabel, yang disebut
events
seperti ini:Dan sebuah tabel bernama
events_meta
seperti ini:Dengan
repeat_start
menjadi tanggal cap waktu unix tanpa waktu (1369008000 sesuai dengan 20 Mei 2013), danrepeat_interval
jumlah dalam detik antar interval (604800 adalah 7 hari).Dengan mengulang setiap hari di kalender, Anda bisa mendapatkan acara berulang menggunakan kueri sederhana ini:
Cukup gantikan dengan cap waktu unix (1299736800) untuk setiap tanggal di kalender Anda.
Perhatikan penggunaan modulo (tanda%). Simbol ini seperti pembagian reguler, tetapi mengembalikan '' sisa '' alih-alih hasil bagi, dan dengan demikian adalah 0 setiap kali tanggal saat ini adalah kelipatan dari repeat_interval dari repeat_start.
Perbandingan Kinerja
Ini jauh lebih cepat daripada jawaban berbasis-meta_keys yang disarankan sebelumnya, yaitu sebagai berikut:
Jika Anda menjalankan EXPLAIN kueri ini, Anda akan mencatat bahwa itu mengharuskan penggunaan buffer gabungan:
Solusi dengan 1 bergabung di atas tidak memerlukan buffer seperti itu.
Pola "Kompleks"
Anda dapat menambahkan dukungan untuk jenis yang lebih kompleks untuk mendukung jenis aturan berulang ini:
atau
Tabel acara Anda dapat terlihat persis sama:
Kemudian untuk menambahkan dukungan untuk aturan-aturan kompleks ini tambahkan kolom
events_meta
seperti:Catatan bahwa Anda hanya perlu baik menentukan
repeat_interval
atau satu setrepeat_year
,repeat_month
,repeat_day
,repeat_week
, danrepeat_weekday
data.Ini membuat pemilihan kedua jenis secara bersamaan sangat sederhana. Lewati saja setiap hari dan isi nilai yang benar, (1370563200 untuk 7 Juni 2013, lalu tahun, bulan, hari, nomor minggu, dan hari kerja sebagai berikut):
Ini mengembalikan semua peristiwa yang berulang pada hari Jumat minggu ke-2, serta setiap peristiwa yang berulang setiap hari Jumat, sehingga mengembalikan kedua peristiwa ID 1 dan 2:
* Sidenote dalam SQL I di atas menggunakan indeks hari kerja default Tanggal PHP , jadi "5" untuk hari Jumat
Semoga ini bisa membantu orang lain sebanyak jawaban asli membantu saya!
sumber
repeat_interval
kolom dan mewakilinya di kolom berikutnya (yaiturepeat_year
, dll.) Untuk baris pertama, situasi pengulangan setiap Senin setelah 20 Mei 2013, dapat diwakili dengan menempatkan 1 direpeat_weekday
dan*
di kolom lainnya.*
. Jadi untuk "setiap bulan pada tanggal 3" Anda baru saja menetapkanrepeat_day
ke 3, sisarepeat
bidang ke * (biarkanrepeat_interval
nol), dan atur repeat_start ke kode waktu unix untuk 3 Maret 2011 menjadi jangkar tanggal Anda.Peningkatan: ganti cap waktu dengan tanggal
Sebagai tambahan kecil untuk jawaban yang diterima yang kemudian disempurnakan oleh ahoffner - dimungkinkan untuk menggunakan format tanggal daripada cap waktu. Keuntungannya adalah:
untuk melakukan ini, ubah DB
repeat_start
agar disimpan sebagai tipe 'tanggal' danrepeat_interval
sekarang tahan beberapa hari daripada detik. yaitu 7 untuk pengulangan 7 hari.ubah baris sql:
untuk:
yang lainnya tetap sama. Sederhana!
sumber
Saya akan mengikuti panduan ini: https://github.com/bmoeskau/Extensible/blob/master/recurrence-overview.md
Pastikan juga Anda menggunakan format iCal agar tidak menemukan kembali roda dan ingat Aturan # 0: JANGAN menyimpan contoh kejadian berulang sebagai baris di basis data Anda!
sumber
attendedEvent
denganbaseInstanceId
daninstanceStartDate
- Yaitu sebagai contoh acara dasar dari mana Anda membuat tampilan kalender aturan berulang dan menggunakan tanggal mulai untuk menentukan informasi pada contoh spesifik itu Lalu entitas ini juga bisa memiliki sesuatu sepertiattendedListId
yang mengarah ke meja lainid
,attendedUserId
Untuk Anda yang tertarik dengan ini, sekarang Anda bisa menyalin dan menempel untuk memulai dalam beberapa menit. Saya menerima saran dalam komentar sebaik mungkin. Beritahu saya jika saya kehilangan sesuatu.
"COMPLEX VERSION":
acara
events_meta
Kode SQL:
juga tersedia sebagai ekspor MySQL (untuk akses mudah)
Contoh kode PHP index.php:
Contoh kode PHP connect.php:
Juga kode php tersedia di sini (untuk keterbacaan yang lebih baik):
index.php
dan
connect.php
Sekarang pengaturan ini akan membawa Anda beberapa menit. Bukan jam. :)
sumber
Sementara solusi yang diusulkan bekerja, saya mencoba menerapkan dengan Kalender Lengkap dan akan membutuhkan lebih dari 90 panggilan basis data untuk setiap tampilan (karena memuat saat ini, sebelumnya, dan bulan depan), yang, saya tidak terlalu senang.
Saya menemukan perpustakaan rekursi https://github.com/tplaner/When di mana Anda hanya menyimpan aturan dalam database dan satu permintaan untuk menarik semua aturan yang relevan.
Semoga ini akan membantu orang lain, karena saya menghabiskan berjam-jam berusaha mencari solusi yang baik.
Sunting: Perpustakaan ini untuk PHP
sumber
When
Anda harus menyimpan semua tanggal reccuring dalam database atau mendapatkan semua event reccuring dan menghasilkan tanggal dalam php no dalam database. Apakah saya benar?When
untuk menghasilkan semua tanggal - yang diisi dari tanggal / aturan tersimpan awal.Mengapa tidak menggunakan mekanisme yang mirip dengan pekerjaan cron Apache? http://en.wikipedia.org/wiki/Cron
Untuk penjadwalan kalender \ saya akan menggunakan nilai yang sedikit berbeda untuk "bit" untuk mengakomodasi acara pengulangan kalender standar - alih-alih [hari dalam seminggu (0 - 7), bulan (1 - 12), hari bulan (1 - 31), jam (0 - 23), min (0 - 59)]
- Saya akan menggunakan sesuatu seperti [Tahun (ulangi setiap N tahun), bulan (1 - 12), hari bulan (1 - 31), minggu bulan (1-5), hari minggu (0 - 7) ]
Semoga ini membantu.
sumber
Saya mengembangkan bahasa pemrograman esoterik hanya untuk kasus ini. Bagian terbaik tentang itu adalah skema yang lebih sedikit dan platform mandiri. Anda hanya perlu menulis program pemilih, untuk jadwal Anda, sintaks yang dibatasi oleh seperangkat aturan yang dijelaskan di sini -
https://github.com/tusharmath/sheql/wiki/Rules
Aturannya dapat diperluas dan Anda dapat menambahkan segala jenis penyesuaian berdasarkan jenis logika pengulangan yang ingin Anda lakukan, tanpa khawatir tentang migrasi skema dll.
Ini adalah pendekatan yang sama sekali berbeda dan mungkin memiliki beberapa kelemahannya sendiri.
sumber
Kedengarannya sangat mirip peristiwa MySQL yang disimpan dalam tabel sistem. Anda dapat melihat struktur dan mencari tahu kolom mana yang tidak diperlukan:
sumber
Standar RRULE dibuat untuk memenuhi persyaratan ini, yakni menyimpan dan memahami rekurensi. Microsoft dan Google sama-sama menggunakannya dalam acara kalender mereka. Silakan baca dokumen ini untuk lebih jelasnya. https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html
sumber
@Rogue Coder
Ini bagus!
Anda cukup menggunakan operasi modulo (MOD atau% di mysql) untuk membuat kode Anda sederhana di akhir:
Dari pada:
Melakukan:
Untuk mengambil ini lebih jauh, seseorang dapat memasukkan peristiwa yang tidak terulang selamanya.
Sesuatu seperti "repeat_interval_1_end" untuk menunjukkan tanggal "repeat_interval_1" terakhir dapat ditambahkan. Namun ini, membuat kueri lebih rumit dan saya tidak bisa benar-benar mengetahui cara melakukan ini ...
Mungkin seseorang bisa membantu!
sumber
Dua contoh yang Anda berikan sangat sederhana; mereka dapat direpresentasikan sebagai interval sederhana (yang pertama adalah empat hari, yang kedua adalah 14 hari). Bagaimana Anda membuat model ini akan sepenuhnya bergantung pada kompleksitas pengulangan Anda. Jika yang Anda miliki di atas benar-benar sesederhana itu, maka simpan tanggal mulai dan jumlah hari dalam interval ulang.
Namun, jika Anda perlu mendukung hal-hal seperti
Atau
Maka itu pola yang jauh lebih kompleks.
sumber