web-dev-qa-db-ja.com

データベースで「定期的なイベント」を表す最良の方法は何ですか?

私はC#でスケジューラーとカレンダーに依存するイベントアプリケーションを開発しようとしています。そのための重要な要件は、データベース内の定期的なイベントを表すことです。データベースで繰り返し発生するイベントを表す最良の方法は何ですか?

詳細:

イベントの作成中、特定のユーザーに招待状を送信します。招待者は、指定されたウィンドウ(会議期間)の間のみミーティングへのログインを許可する必要があります。または、招待者が5分前にログインしようとしたときにログインを拒否することもできます。会議の予定された開始。

43
Varma

sysjobssysjobsschedule および sysschedules SQL Serverのテーブルは、これをかなりうまく処理します。私は車輪の再発明をしません、私は彼らのデザインをコピーするだけです。

sysschedulesの重要なフィールドの一部を以下に示します

freq_type

このスケジュールでジョブが実行される頻度。

1 = 1回のみ

4 =毎日

8 =毎週

16 =毎月

32 =毎月、freq_intervalを基準

64 = SQLServerエージェントサービスの開始時に実行されます

128 =コンピューターがアイドル状態のときに実行されます

freq_interval

ジョブが実行される日。 freq_typeの値によって異なります。デフォルト値は0で、freq_intervalが使用されていないことを示します。 freq_typeの値freq_intervalへの影響

1 (once) freq_interval is unused (0)

4(毎日)freq_interval日ごと

8(毎週)freq_intervalは、次の1つ以上です。1=日曜日2 =月曜日4 =火曜日8 =水曜日16 =木曜日32 =金曜日64 =土曜日

16(毎月)その月のfreq_interval日に

32(月次、相対)freq_intervalは次のいずれかです:1 =日曜日2 =月曜日3 =火曜日4 =水曜日5 =木曜日6 =金曜日7 =土曜日8 =日9 =平日10 =週末

64(SQL Serverエージェントサービスの開始時に開始)freq_intervalは未使用(0)

128(コンピューターがアイドル状態のときに実行)freq_intervalは未使用(0)

freq_subday_type

Freq_subday_intervalの単位。次のいずれかの値になります。値説明(単位)

1指定した時間

2秒

4分

8時間

freq_subday_interval

ジョブの各実行の間に発生するfreq_subday_type期間の数。

freq_relative_interval

各月にfreq_intervalが発生したとき、freq_intervalが32(月次相対)の場合。次のいずれかの値になります。

0 = freq_relative_intervalは使用されていません

1 =最初

2 = 2番目

4 = 3番目

8 = 4番目

16 =最後

freq_recurrence_factor

スケジュールされたジョブの実行間の週数または月数。 freq_recurrence_factorは、freq_typeが8、16、または32の場合にのみ使用されます。この列に0が含まれている場合、freq_recurrence_factorは使用されません。

38
Bob

繰り返しルール自体を格納するには、 RFC 5545 の削減バージョンを使用できます(そして、大幅に削減することをお勧めします)。他のものは別として、それはあなたが望むなら他のアプリケーションにエクスポートすることを簡単にします。

その決定を行った後、データベース側では、イベントの各オカレンスを保存するか、繰り返しイベントの1つのレコードのみを保存するかを決定し、必要に応じて拡張する必要があります。する必要があります。明らかに、すべてがすでに拡張されている場合は、データベースへのクエリがかなり簡単になりますが、保守が難しくなります。

テストが難しいかもしれないかなり複雑なSQLを書くのが好きでない限り(そして、あらゆる種類のコーナーケースに対してlotのユニットテストが必要になるでしょう)、データベース自体を比較的作成することをお勧めします。ばかげている」と言って、ほとんどのビジネスロジックをJavaまたはC#のような言語で記述します。もちろん、データベースによっては、どちらもストアドプロシージャに埋め込むことができます。

あなたが自分自身に尋ねる必要があるもう一つのことはあなたが対処する必要があるかどうかです例外イベントへ-時間/場所を変える一連の1つのイベントなど。

私はカレンダーについてある程度の経験があります(昨年のほとんどは Google Sync ActiveSyncを介してカレンダーのビットに取り組んでいます)。状況が複雑になることを警告しますreally =すばやく。 「範囲外」とみなすことができるものはすべて祝福です。特に、複数のタイムゾーンで作業する必要がありますか?

ああ、そして最後に-カレンダー操作で実際の演算を行うときは、非常に注意してください。 Javaを使用する場合は、組み込みのCalendar/Dateクラスではなく、-お願いJoda Time を使用してください。彼らはあなたをたくさん助けるでしょう。

24
Jon Skeet

ここで受け入れられた答えは複雑すぎます。たとえば、イベントが5日ごとに発生する場合、5はfreq_intervalに格納されますが、5週間ごとに発生する場合、5はfreq_recurrenceに格納されます。最大の問題は、freq_intervalがfreq_typeの値に応じて3つの異なる意味を持つことです(毎日の繰り返しの発生間の日数、毎月の繰り返しの月の日、または毎週または毎月の相対的な曜日)。また、1,2,4,8 ...タイプのシーケンスは、不要で役に立たない場合に使用されます。たとえば、freq_relative_intervalは"one of"可能な値のみにすることができます。これは、複数の選択肢を選択できるチェックボックスタイプの入力ではなく、ドロップダウンボックスまたはラジオボタンタイプの入力と一致します。コーディングと人間の読みやすさのために、このシーケンスは邪魔になり、1,2,3,4 ...を使用する方が簡単で効率的で適切です。最後に、ほとんどのカレンダーアプリケーションは、サブデイ間隔(1日に複数回発生するイベント-非常に多くの秒、分、または時間ごと)を必要としません。
しかし、これを言っても、その答えは私がこれをどのように行っているかについての私の考えを洗練するのに役立ちました。それを他の記事と組み合わせて一致させ、Outlookのカレンダーインターフェイスやその他のいくつかのソースに表示されるものから、次のように思いつきました。

繰り返し
0 =再発なし
1 =毎日
2 =毎週
3 =毎月

recurs_interval
これは、再発間の期間の数です。イベントが5日ごとに繰り返される場合、これは5になり、recursは1になります。イベントが2週間ごとに繰り返される場合、これは2になり、recursはになります。 a2。

recurs_day
ユーザーが月次タイプの繰り返しを選択した場合、その月の特定の日(例:10日または14日)。これにはその日付があります。ユーザーが毎月または特定の月の繰り返しを選択しなかった場合、値は0です。それ以外の場合、値は1〜31です。

recurs_ordinal
ユーザーが月次タイプの繰り返しを選択したが、通常のタイプの日(例:第1月曜日、第2木曜日、最終金曜日)を選択した場合。これにはその序数があります。ユーザーがこのタイプの繰り返しを選択しなかった場合、値は0です。
1 =最初
2 =秒
3 = 3番目
4 = 4番目
5 =最後

recurs_weekdays
毎週および毎月の通常の再発の場合、これは再発が発生する平日を格納します。 1 =日曜日
2 =月曜日
4 =火曜日
8 =水曜日
16 =木曜日
32 =金曜日
64 =土曜日

つまり、例:
つまり、土曜日と日曜日の4週間ごとに

  • 繰り返し= 2 ==>毎週の繰り返し
  • recurs_interval = 4 ==>ごと4
  • recurs_weekdays = 65 ==>(土曜日= 64+日曜日= 1)
  • recurs_dayおよびrecurs_ordinal = 0 ==>未使用

同様に、毎月第1金曜日の6か月ごとに

  • 繰り返し= 3 ==>毎月の繰り返し
  • recurs_interval = 6 ==>ごと6
  • recurs_ordinal = 1 ==>最初の出現時
  • recurs_weekdays = 32 ==>金曜日

別のフィールドの価値に応じて3つのまったく異なることを意味するフィールドを持つというこのビジネスはありません。

ユーザーインターフェイス側では、ユーザーに日付、開始時刻、終了時刻を指定させます。次に、なし以外のタイプの再発が必要かどうかを指定できます。その場合、アプリはWebページの関連セクションを展開して、上記のものに必要なオプションをユーザーに提供します。これは、毎日の繰り返しの下に「毎週」がないことを除いて、Outlookのオプションとよく似ています(すべての月〜金曜日に毎週再発)、毎年再発はありません。再発がある場合は、今日から1年以内の終了日を指定するようにユーザーに要求します(ユーザーはそれを希望し、コードを簡素化します)-終わりのない再発や「#の後に終了」は行いません#発生。」

これらのフィールドをユーザーの選択とともにイベントテーブルに格納し、すべてのオカレンスを含むスケジュールテーブルに展開します。これにより、衝突検出(私は実際に施設予約アプリケーションを実行しています)と個々の発生の編集または将来の発生のリファクタリングが容易になります。

私のユーザーはすべてCSTにいます、そして私はそれについて良い主に感謝します。これは今のところ便利な簡略化であり、将来ユーザーベースがそれを超えて拡大する場合は、十分に分離されたタスクとして、それをどのように処理するかを理解できます。

[〜#〜] update [〜#〜]これを最初に書いたので、「Everyweekday」で毎日のオカレンスを追加しました。ユーザーは、1週間の木曜日から翌週の火曜日までの平日にのみ発生するイベントに毎週の繰り返しを使用できると考えるのに少し苦労しました。彼らがそれを行うことができる別の方法がすでにあったとしても、彼らがこれを持っていることはより直感的でした。

7
user4843530

定期的なイベントを2つの別個のものとしてデータベースに記録します。まず、イベントテーブルに、イベントの発生をすべて記録します。次に、繰り返しイベントを設定するために要求する詳細を記録する繰り返しテーブルを用意します。開始日、周期、発生回数など.

次に、繰り返しのPKを各イベントレコードにFKとして入れることで、すべてをまとめることを考えるかもしれません。ただし、より適切な設計は、イベントテーブルを2つのテーブルに正規化することです。1つはイベントの最低限のものであり、もう1つは詳細があり、複数のイベントを参照できるようになります。このようにして、繰り返し発生するかどうかに関係なく、すべてのイベントレコードにeventdetailsテーブルのPKへのFKがあります。次にeventdetailsで、繰り返しのPKを議題、招待者などと一緒にどこかに記録します。繰り返しの記録は何も引き起こしません。たとえば、すべての定期的なイベントのリストが必要な場合は、FKがnull以外のすべてのイベントのeventdetailsを調べて繰り返します。

繰り返しデータが変更されたときにイベントを挿入または削除できるように、これらすべてを同期するように注意する必要があります。

0
Michael Dillon

私もこれについて考えてきましたが、実装はしていませんが、これらは簡単な解決策に対する私の考えです。

定期的なイベントを設定するときは、ユーザーに「終了日」を指定してもらい、それぞれに個別のイベントを作成してもらいます(定期的なオプションに基づいて)。定期的なイベントであるため、これらのそれぞれに一意の「定期的なID」を設定します。このIDは、イベントを定期的なものとしてマークするために使用されます。将来のイベントを変更した場合は、新しい「定期的なID」を使用して定期的なイベントを削除および再作成することで、これを残りの将来のイベントに適用するようにユーザーに求めることができます。また、この定期的なイベントを、以前に変更されたイベントと区別します。

これが理にかなっていることを願って、コメントをお願いします。

0
Mark Redman