1

私はイベントカレンダーを作成しようとしていますが、最初は非常に小さいものでしたが、非常に大きいことが判明する可能性があります。そのために、可能な限り将来を保証しようとすると、過去に発生したすべてのイベントがデータベースから削除されます。ただし、次のイベントがいつ開始されるかを示すために、定期的なイベントの開始日を変更するのは悪い習慣ですか?これにより、データベースが更新される頻度にもよりますが、理論的には過去1週間を超えて開始されるイベントはないため、検索クエリの実行が容易になります。

これを行うためのより良い方法はありますか?

私の現在の意図は、イベントの詳細と、それが毎年、毎月、毎週、または毎日の繰り返しであるかどうかの列をリストした表を作成することです。次に誰かが2つの日付の間のイベントを検索するとき、私は単に各行を見て、(EVENT START <= SEARCH FINISH && EVENT FINISH> = SEARCH START)かどうかを確認します。次に、これによりすべての可能なイベントが取得され、定期的なイベントをチェックして、指定された期間中に発生するかどうかを確認する必要があります。これを具体的にどのように達成するかについて、私はここで少し行き詰まりました。私の考えは次のとおりです。

毎年:イベント開始+1年<=検索終了の場合|| イベント終了+1年>=検索開始; イベント開始+年なし>検索終了まで+2年などを繰り返します。

毎月:上記と同じですが、毎回+1か月です。

毎週:上記と同じですが、EVENTSTARTとEVENTFINISHは、EVENT START + 7 DAYS REPEATED> SEARCH FINISHまで、各反復の繰り返しの間にプラス7日が加算されます。

毎日:上記と同じですが、1週間の7日ではなく、日数の違いはありません。これは、14日ごと(2週間)、10日ごとなどを指定するために使用できます。毎週でもこの方法を使用できます。

ただし、これを実現するために作成する必要のあるクエリについて考えると、非常に面倒で、おそらく低速になると思わざるを得ません。私が望む結果を達成するためのより良い方法はありますか?月の第1月曜日、月の最終金曜日、または毎年4月の第2土曜日に発生するようなことを行う方法をまだ見つけていません。これらの後者のオプションも可能ですか?

-編集:以下に追加:

私が作成しているものについてもう少し説明すると、少し役立つかもしれません。そうすれば、それに関してガイダンスを与えることができます。

私は、組織が1回限りのイベントでも定期的なイベントでも(毎日、毎週、毎月、毎月第1火曜日など)イベントを追加できるWebサイトを作成しています。サイトのユーザーは、選択した距離(任意の10、25、50、100マイル、国全体)内のイベントを、設定された日付または2つの指定された日付の間で検索できます。数年離れています(明らかに、使用される日付に応じて、はるか先のイベントは最小限になるか、存在しなくなります)。

EVENTSテーブル自体には、現在、場所、コスト、年齢層など、イベントに関する多くの情報が保持されています。イベントが指定された検索パラメータ?明らかに、詳細なページビューまで、この情報のすべてが必要なわけではありません。名前、場所、コスト、簡単な説明だけかもしれません。

猫の皮を剥ぐ方法はたくさんありますが、どうやって皮を剥ぐのかわかりません。私が苦労している最大のことは、再帰が指定された日付内にあるかどうかをクエリが認識できるようにデータを構造化する方法です。また、2 lat / long間の距離を計算する数学は比較的複雑なので、この計算をクエリに組み込むことができる必要があります。そうでない場合は、とにかくPHPで計算を行います。確かに、この方法で処理する結果は少なくなりますが、それでも実行する必要があります。

さらにアドバイスをいただければ幸いです。

4

3 に答える 3

3

繰り返しごとにイベントを作成する必要はありません。イベントの再発方法を定義する詳細を保存することをお勧めします。この質問はSOで何度も回答されています。

これを行う1つの方法は、次のような構造を使用することです-

tblEvent
--------
id
name
description
date

tblEventRecurring
-----------------
event_id
date_part
end_date

次に、このようなクエリを使用してイベントを取得できます-

SELECT *
FROM `tblEvent`
LEFT JOIN `tblEventRecurring`
    ON `tblEvent`.`id` = `tblEventRecurring`.`event_id`
WHERE (`tblEvent`.`date` = CURRENT_DATE AND `tblEventRecurring`.`event_id` IS NULL)
OR (
    CURRENT_DATE BETWEEN `tblEvent`.`date` AND `tblEventRecurring`.`end_date`
    AND (
        (`tblEventRecurring`.`date_part` = 'D') OR
        (`tblEventRecurring`.`date_part` = 'W' AND DAYOFWEEK(`tblEvent`.`date`) = DAYOFWEEK(CURRENT_DATE)) OR
        (`tblEventRecurring`.`date_part` = 'M' AND DAYOFMONTH(`tblEvent`.`date`) = DAYOFMONTH(CURRENT_DATE))
    )
)

UPDATE指定された日付範囲のイベントを返す次の例を追加しました。

特定の日付範囲の日付を返す場合、上記のクエリを日付範囲を表すテーブルに結合できます-

SET @start_date = '2012-03-26';
SET @end_date = '2012-04-01';

SELECT *
FROM (
    SELECT @start_date + INTERVAL num DAY AS `date`
    FROM dummy
    WHERE num < (DATEDIFF(@end_date, @start_date) + 1)
) AS `date_list`
INNER JOIN (
    SELECT `tblEvent`.`id`, `tblEvent`.`date`, `tblEvent`.`name`, `tblEventRecurring`.`date_part`, `tblEventRecurring`.`end_date`
    FROM `tblEvent`
    LEFT JOIN `tblEventRecurring`
        ON `tblEvent`.`id` = `tblEventRecurring`.`event_id`
    WHERE `tblEvent`.`date` BETWEEN @start_date AND @end_date
    OR (`tblEvent`.`date` < @end_date AND `tblEventRecurring`.`end_date` > @start_date)
) AS `events`
    ON `events`.`date` = `date_list`.`date`
    OR (
        `date_list`.`date` BETWEEN `events`.`date` AND `events`.`end_date`
        AND (
            (`events`.`date_part` = 'D') OR
            (`events`.`date_part` = 'W' AND DAYOFWEEK(`events`.`date`) = DAYOFWEEK(`date_list`.`date`)) OR
            (`events`.`date_part` = 'M' AND DAYOFMONTH(`events`.`date`) = DAYOFMONTH(`date_list`.`date`))
        )
    )
WHERE `date_list`.`date` BETWEEN @start_date AND @end_date
ORDER BY `date_list`.`date`;

必要に応じて、SQL変数をPHP変数に置き換えることができます。イベントのない日を表示するにINNER JOINは、2つの派生テーブルdate_listevents、の間をLEFTJOINに変更できます。

このテーブルdummyは、0から必要と予想されるものまでの番号を持つ単一の列で構成されています。この例では、1か月をカバーするのに十分なデータを含むダミーテーブルを作成します。別のテーブルのAIPKを使用して簡単にデータを入力できINSERT... SELECT...ます-

CREATE TABLE `dummy` (
    `num` SMALLINT UNSIGNED NOT NULL PRIMARY KEY
);
INSERT INTO `dummy` VALUES
    (00), (01), (02), (03), (04), (05), (06), (07), (08), (09),
    (10), (11), (12), (13), (14), (15), (16), (17), (18), (19),
    (20), (21), (22), (23), (24), (25), (26), (27), (28), (29),
    (30), (31);
于 2012-03-25T22:36:47.870 に答える
1

分割する定期的なイベントIDを使用して、まだ発生していないベント用のテーブルを1つ用意します。したがって、nullの繰り返しveentidを使用してそこに1つだけ突くことができます。過去のものなどを取り除く/アーカイブする

定期的なイベントに関するデータについては、もう1つ用意してください。

繰り返しとしてマークされたイベントが発生したら、繰り返しテーブルに戻って、それが有効になっているかどうかを確認し(範囲を追加する、つまり3か月間毎週これを行う)、すべて問題がない場合は、新しいレコードを追加します次回それが発生するために。

とにかくそれを行う1つの方法であり、2つの異なる目的でイベント開始を使用する問題を取り除きます。これが、コードが複雑になる理由です。

これから将来の仕事が必要な場合。つまり、来月に行う必要のあるすべてのことです。

それはユニオンクエリになります。1つはすべての「現在のジョブ」を取得し、1つは翌月に繰り返されるすべてのジョブを取得します。

これを十分に強調することはできません。データ設計を正しくするために、コードは「ちょうど起こる」のです。2つの異なるニーズに対応する1つのフィールド「開始日」のようにデータが混乱している場合は、データに近づくたびに、その二重の使用に対処する必要があります。一度それを忘れると、あなたは痛みを伴う混乱から災害まで何でも手に入れます。

Recurring_Start_Date列を追加すると、現在の計画よりも優れていると思いませんか。あなたはこの質問をすることはないでしょう、あなたのデータはあなたのニーズに合うでしょう。

于 2012-03-25T17:49:07.507 に答える
0

新しいイベントを作成するよりも、イベントを頻繁に検索することになると思います。イベントの作成中に、イベントの発生ごとに、妥当な時間まで(おそらく、来年または2年)レコードを作成します。

また、「毎月第3木曜日」のようなことも少し簡単になります。クエリで計算を実行しようとすると、難しく、おそらく遅くなります。

于 2012-03-25T20:46:25.063 に答える