私はまさにこの問題に取り組んでおり、このスレッドを読むまではiCalendar(rfc 2445 )の間隔を完全に空けていたので、これがどれだけうまく統合されるか、統合されないかはわかりません。とにかく、私がこれまでに思いついたデザインは次のようになります。
- 繰り返し発生するイベントのすべてのインスタンスを、少なくとも発生する前に保存することはできないため、イベントの最初のインスタンスを実際の日付、オプションの有効期限、およびnull許容のrepeat_unitフィールドとrepeat_incrementフィールドとして格納するテーブルが1つあります。繰り返しを説明します。単一インスタンスの場合、repitionフィールドはnullです。それ以外の場合、単位は「日」、「週」、「月」、「年」になり、増分は、次の発生の開始日に追加する単位の倍数になります。
- 過去のイベントを保存することは、モデル内の他のエンティティとの関係を確立する必要がある場合にのみ有利であるように思われます。その場合でも、すべての場合に明示的な「イベントインスタンス」テーブルを用意する必要はありません。他のエンティティがすでに日付/時刻の「インスタンス」データを持っている場合は、イベントへの外部キー(または多対多の場合は結合テーブル)で十分である可能性があります。
- 「このインスタンスを変更する」/「将来のすべてのインスタンスを変更する」を行うために、私はイベントを複製し、古いイベントを期限切れにすることを計画していました。したがって、単一のインスタンスを変更するには、最後のオカレンスで古いインスタンスを期限切れにし、変更を加えて繰り返しなしで新しい一意のオカレンスのコピーを作成し、次のオカレンスで元のインスタンスの別のコピーを作成します。将来。今後のすべてのインスタンスの変更も同様です。元のインスタンスを期限切れにして、変更と繰り返しの詳細を含む新しいコピーを作成するだけです。
これまでのところ、この設計で見られる2つの問題は次のとおりです。
- MWFタイプのイベントを表現するのが難しくなります。可能ですが、ユーザーはM、W、Fで毎週繰り返される3つの個別のイベントを作成する必要があり、必要な変更はそれぞれ個別に行う必要があります。これらの種類のイベントは私のアプリでは特に有用ではありませんが、モデルに疣贅を残し、私が望むよりも普遍性が低くなります。
- イベントをコピーして変更を加えることで、イベント間の関連付けを解除できます。これは、一部のシナリオで役立つ場合があります(または、場合によっては問題が発生する可能性があります)。理論的には、イベントテーブルに「copied_from」idフィールドを含めて、イベントが始まったのですが、そのようなものがどれほど役立つかを十分に考えていませんでした。一つには、親子の階層関係はSQLからクエリを実行するのが面倒なので、そのデータをクエリするコストを上回るメリットはかなり重い必要があります。代わりにネストされたセットを使用することもできます。
最後に、ストレートSQLを使用して特定の期間のイベントを計算することは可能だと思いますが、正確な詳細を把握していないため、クエリは通常、煩雑すぎて価値がないと思います。ただし、議論のために、次の式を使用して、特定の月とイベントの年との間の月の差を計算できます。
(:month + (:year * 12)) - (MONTH(occursOn) + (YEAR(occursOn) * 12))
最後の例に基づいて、MODを使用して、月の差が正しい倍数であるかどうかを判断できます。
MOD(:month + (:year * 12)) - (MONTH(occursOn) + (YEAR(occursOn) * 12), repeatIncrement) = 0
とにかく、これは完璧ではありません(期限切れのイベントを無視しない、イベントの開始/終了時間を考慮しないなど)ので、やる気を起こさせる例としてのみ意図されています。一般的に言って、ほとんどのクエリは複雑になりすぎると思います。おそらく、特定の範囲内で発生するイベント、または範囲の前に期限切れにならないイベントを照会し、SQLではなくコードでインスタンス自体を計算する方がよいでしょう。本当にデータベースに処理を実行させたい場合は、ストアドプロシージャを使用すると、作業が大幅に楽になります。