6

私は、なし、毎日、毎週、毎月、毎年繰り返されるカレンダーアプリケーションを設計しています。私の要件の 1 つは、「2 つのイベントが重複してはならない」ということ です。データを保存するテーブルの名前

イベント

田畑

dtstart - イベント開始時刻

dtend - イベント終了時刻

次の 2 つのケースを考えてみましょう。

Event1 8 月 15 日 午後 3:00 ~ 午後 4:00 再発 - なし

Event2 8 月 15 日午後 2:00 ~ 午後 5-00 再発 - なし

上記の場合、次の SQL クエリは魅力的に機能します

String sqlQuery = "SELECT * FROM Events WHERE dtstart AND dtend BETWEEN %d AND %d";

sqlQuery = String.format(sqlQuery, dtstart, dtend);

ここで、ケース 2 を考えてみましょう。

Event1 8 月 15 日 午後 3:00 ~ 午後 4:00 繰り返し - 8 月 20 日まで毎日

Event2 8 月 18 日午後 2:00 ~ 午後 5-00 再発 - なし

2 つの sqlQuery が失敗した場合、同じ日付 (8 月 18 日) のイベントの開始時刻と終了時刻がチェックされるためです。私の場合、クエリは 8 月 15 日の競合する時間を表示するはずです。

定期的なイベントもチェックされるように、SQL クエリを手伝ってください。

イベント テーブルには、開始時刻、終了時刻、最後に発生した日付、および発生タイプを格納します。

データベーススキームは次のとおりです

テーブル名: イベント

タイトル| dtstart | dtend | リピートタイプ| 最後の発生

4

3 に答える 3

1

新しく挿入された(または更新された)単一のイベントに重複があるかどうか(データベースにすでに存在するイベントのいずれかに重複があるかどうかではない)を検出したいと思いますか?

その場合、(クライアント言語で)手続き的に(クライアント言語で)[s, e]新しく挿入されたイベントの「リピートタイプ」に基づいてすべての開始/終了間隔を生成し、これらの間隔ごとに次のクエリを実行して重複を検出できます(私はOracle構文を使用しています)ここでは、SQLiteも同様であると想定しています):

-- A time interval must be either completely "to the left" or completely
-- "to the right" of the other time interval for them not to overlap.
SELECT * FROM EVENT
WHERE
    NOT(
        (:s < DTSTART AND :s < DTEND AND :e < DTSTART AND :e < DTEND)
        OR (:s > DTSTART AND :s > DTEND AND :e > DTSTART AND :e > DTEND)
    )

ただし、優れたパフォーマンスは期待しないでください(特に、イベントの繰り返し回数が多い場合、DTSTART / DTENDがインデックスに登録されていない場合、またはSQLiteがそのインデックスを適切に活用できない場合)。

パフォーマンスのためには、すべてのイベントをメモリにキャッシュし、すべての処理をクライアント側で実行する方がよいでしょう。これにより、ヒューリスティックを使用して一部の処理を「短絡」することがより簡単になります。例えば:

  • 2つのイベントの「繰り返しタイプ」が同じである場合、繰り返しを気にせずに最初の間隔を比較できます。最初に一致しない場合、一致することはありません。
  • あるイベントの「最後の発生」が「dtstart」でなくても他のイベントの前にある場合、「リピートタイプ」に関係なくそれらは一致しません。
  • 等...

処理データベース側のすべてが本当に必要で、(クエリ)パフォーマンスが必要な場合は、おそらくある種の地理空間/多次元インデックスを検討しており、インデックスを作成できるように、イベントの繰り返しをデータベースに実際に保存する必要があります。 、おそらく挿入パフォーマンスを損なうでしょう。私はSQLiteに精通しておらず、SQLiteがこの種のインデックス作成をサポートしているかどうかを知りません...

于 2011-08-08T11:35:58.090 に答える
1

かなりのコードになります。「なし」の発生イベント B の前に開始される毎週の再発イベント A のチェックの概要を説明します。

  1. 両方が「なし」であるかのようにチェックしてください。
  2. 重複しない場合は、A.dtstart と dtend に 7 日を追加します。
  3. 再び確かめる。
  4. チェックが成功するか、A.dtstart > B.dtend になるまで繰り返します。

毎日、毎月などにこれのバリアントを使用します。両方のイベントが同じ発生スケジュールである場合、これも機能します。

それらが異なるループにある場合は、他の間隔で反復する 2 番目の外側のループが必要です。停止条件はトリッキーになる可能性があります。これは、両方の間隔サイズの最小公倍数のようなものになると思います。

このコードはすべてホスト言語で実行する必要があり、SQLite でストアド プロシージャ言語として直接使用できます。これがどのように行われるかは、ホスト言語によって異なります。

于 2011-08-15T02:02:45.087 に答える
1

重複するイベントを繰り返しチェックする単一の SQL ステートメントは考えられませんが、いくつかの提案があります。

  1. すべての定期的なイベントに明確な終了日がある場合は、 、 、でEventInstance構成されるテーブルを作成できます。次に、テーブルにとTriggersを記述して、 に格納されているすべてのインスタンスを更新します。次に、クエリをテーブルで使用できます。しかし、私は SQLite の経験がないので、トリガーをサポートしているかどうかはわかりません。EventIDStartTimeEndTimeAFTER INSERTAFTER UPDATEAFTER DELETEEventEventInstanceEventInstance

  2. データベースにストアド プロシージャを記述して、プロシージャ コードでチェックします (これも SQLite がサポートしている場合)。

  3. Java コードで重複するイベントを確認します。

于 2011-08-04T18:02:26.247 に答える