2012-02-18 34 views
0

私の最初の投稿はstackoverflowですので、私の質問がここのルールに正しく当てはまらない場合は教えてください。特定の範囲内の繰り返し日付を見つける

PHP/Mysqlで検索を実装しようとしていますが、特定の時間範囲内のすべてのエントリが検索されます。エントリは、有効な平日を指定します。

これは、データベースモデル:

CREATE TABLE offer (
    offer_id int unsigned not null auto_increment, 
    start int unsigned not null, 
    primary key(offer_id), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE offer_weekdays (
    offer_id int unsigned not null, 
    weekday tinyint unsigned not null, 
    index (offer_id), 
    foreign key (offer_id) references offer(offer_id) 
      ON delete restrict ON update cascade, 
    unique key (offer_id, weekday) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

テーブル提供エントリを記述し、それが利用可能である場合(カラム開始(タイムスタンプ))から。テーブル* offer_weekdays *は、どの曜日にエントリが繰り返されるかを指定します。各エントリは、いくつかの異なる平日に繰り返すことができます。

特定のタイムスタンプ範囲で使用できるすべてのエントリを取得する機能を実装したいと考えています。この問題を解決するための私のアイデアは、遅いか正確さが欠けています。

私はどんなヒントもありがとうございます。前もって感謝します!

次のエントリがデータベースに格納されている:

  1. スタート:2011-01-11 10時(火)、繰り返さ:火
  2. スタート:2011 -01-11午前8時00分(火)、繰り返さ:火
  3. スタート:2011-01-12 12:00(水)は、繰り返し:水、木、金

検索された時間範囲は2012-01-10 09:00(Tue)から2012-01-11 11:00(Wed)です。

結果:

  1. が見つからない
  2. を見つけました。曜日の範囲に合っていますが、08:00にのみ有効ですが、 は09:00から検索されます。
  3. が見つかりません。それは12:00に有効ですが、検索は11:00までです。

検索された時間範囲が1週間にわたって重複している場合は、すべてのエントリを見つける必要があります。

+0

オファーの終了時刻を保存しないでください。 2012-01-19から2012-01-25までのすべてのオファーが必要な場合は、2012-01-29以降に開始される各オファーはどれですか? (その期間は平日になるためです) –

+0

私はそれを明確にするための例を追加しました。それ以上の質問については私に尋ねてください。 – Normalo

+0

あなたの例では、年月日または平日のタイプミスですか? –

答えて

0

それはあなたがするとき

The offer starts within the search interval, OR 
(the offer starts *before* search interval and 
start time of the offer >= start time of the search range 
as long as repeating weekdays match) 

選択するように私は私がその権利を持って、本当に、本当にわからないですね。だから私は問題を別の見方を取るつもりです。私はUnixエポックの代わりにSQLタイムスタンプを使うつもりだから、誰もが何が起こっているのかを見ることができます。

また、私は終わりの夜中に提供を終了すると仮定しています。今は私にとって意味のある他の仮定はないようです。

create table offerings (
    offer_id integer not null, 
    offer_start timestamp not null, 
    offer_end timestamp not null check (offer_end > offer_start), 
    primary key (offer_id, offer_start) 
); 

-- Offer 1 starts 2012-01-10 10:00, ends 2012-01-10 23:59, repeats every Tue. 
insert into offerings values (1, '2012-01-10 10:00', '2012-01-10 23:59'); 
insert into offerings values (1, '2012-01-17 10:00', '2012-01-17 23:59'); 
insert into offerings values (1, '2012-01-24 10:00', '2012-01-24 23:59'); 
insert into offerings values (1, '2012-01-31 10:00', '2012-01-31 23:59'); 

-- Offer 2 starts 2012-01-10 08:00, ends 2012-01-10 23:59, repeats every Tue. 
insert into offerings values (2, '2012-01-10 08:00', '2012-01-10 23:59'); 
insert into offerings values (2, '2012-01-17 08:00', '2012-01-17 23:59'); 
insert into offerings values (2, '2012-01-24 08:00', '2012-01-24 23:59'); 
insert into offerings values (2, '2012-01-31 08:00', '2012-01-31 23:59'); 

-- Offer 3 starts 2012-01-11 12:00, ends 2012-01-11 23:59, repeats every Wed, Thu, Fri. 
insert into offerings values (3, '2012-01-11 12:00', '2012-01-11 23:59'); 
insert into offerings values (3, '2012-01-12 12:00', '2012-01-12 23:59'); 
insert into offerings values (3, '2012-01-13 12:00', '2012-01-13 23:59'); 

insert into offerings values (3, '2012-01-18 12:00', '2012-01-18 23:59'); 
insert into offerings values (3, '2012-01-19 12:00', '2012-01-19 23:59'); 
insert into offerings values (3, '2012-01-20 12:00', '2012-01-20 23:59'); 

insert into offerings values (3, '2012-01-25 12:00', '2012-01-25 23:59'); 
insert into offerings values (3, '2012-01-26 12:00', '2012-01-26 23:59'); 
insert into offerings values (3, '2012-01-27 12:00', '2012-01-27 23:59'); 

ここで選択は簡単です。

select * 
from offerings 
where offer_start >= '2012-01-10 09:00' 
    and offer_end <= '2012-01-11 11:00'; 

offer_id offer_start   offer_end 
-- 
1   2012-01-10 10:00:00 2012-01-10 23:59:00 

したがって、このオファリング表と同じ結果を戻すビューを作成できる場合は、そのビューを問い合せるだけです。

ここには3つのレッスンがあります。

  1. あなたを混乱させてはいけません。あなたが必要とするものを探してください。
  2. イースターの問題を忘れないでください。
  3. を提供テーブルにそれを簡素化した後(あなた何かがあなたにべきを意味するものではありません。計算できるという理由だけで)、私はまだない私は基準を理解すると確信しています。コメントと修正後の

その後、。 。 。

-- PostgreSQL 
create table offerings (
    offer_id integer not null, 
    offer_at timestamp not null, 
    primary key (offer_id, offer_at) 
); 

-- A little data for offer 1. Inserts for 2 and 3 are similar. 
insert into offerings 
select 1 offering_id, '2011-01-11 10:00'::timestamp + (n || ' days')::interval offer_at 
from generate_series(0, 1000, 7) n 
where '2011-01-11 10:00'::timestamp + (n || ' days')::interval < '2012-03-01'; 

クエリは、もう一度死んでしまう。 (そして、少しの運で、実際にこの時間を修正します。)これらのクエリの両方が唯一のオファー番号1

select * 
from offerings 
where offer_at between '2012-01-10 09:00' and '2012-01-10 11:00' 

select * 
from offerings 
where offer_at between '2012-01-10 09:00' and '2012-01-11 11:00' 

を返します。それらについての最もよい事はそれを基になるデータが正確であると仮定すると、それは明らかだ、ということですクエリは正しいことを実行しています。コードのトラブルシューティングよりもデータのトラブルシューティングがずっと簡単です。

+0

新しい祝祭日を毎週繰り返していますか?それは、あまりにも多くのデータとメンテナンスを引き起こすので、将来の日付のバックグラウンドジョブによってエントリを継続的に追加する必要があります。 – Normalo

+0

@Normalo:あなたのデータのロジックは正しいですか? –

+0

私のコメントをより明確にするために:2012-02-24 09:00から2012-02-25 11:00まで検索すると、それは私に提供1を与えるはずです。 – Normalo

関連する問題