わかりました、私はそれが価値があるもののためにこれに投入します.
かなりの数のことを処理する必要があります。
- 高速で高性能なクエリ
- 時間の任意の増分、9:01 PM、12:14 など。
- 国際 (?) - これがタイムゾーンでも問題になるかどうかはわかりませんが、少なくとも私の場合は、ここに精通している誰かが自由にチャイムを鳴らしてください。
- 開館~翌日休館(正午開館、午前2時閉館)
- 複数の時間帯 / 日
- 特定の日 (休日など) を上書きする機能
- 上書きを繰り返す機能
- 任意の時点でクエリを実行し、ビジネスを開始する機能 (現在、未来の時間、過去の時間)
- 閉店間近のビジネスの結果を簡単に除外する機能 (30 分以内に閉店するビジネスをフィルター処理します。食品/飲料業界では、閉店の 5 分前に現れるようなユーザーをユーザーにしたくありません)
私は提示されたアプローチの多くが好きで、それらのいくつかから借りています。私のウェブサイトやプロジェクトでは、考慮に入れる必要があるものは何でも、何百万ものビジネスがあり、ここでのアプローチのいくつかは、個人的にうまく拡張できないようです。
アルゴリズムと構造について私が提案するものは次のとおりです。
世界中で、いつでも、どこでも、1 週間は 7 日という具体的な仮定を立てる必要があります。1日は1440分です。可能なオープン/クローズの分の順列の数は限られています。
具体的ではありませんが、適切な仮定: オープン/クローズの議事録の多くの順列は、実際に保存されている順列の合計を削減する企業間で共有されます。私の人生には、このアプローチの実際の可能な組み合わせを簡単に計算できた時期がありましたが、誰かがそれを支援/有用だと考えることができれば、それは素晴らしいことです.
私は 3 つのテーブルを提案します: 読むのをやめる前に、これらのテーブルのうちの 2 つが十分に小さいキャッシュになることを現実世界で考えてみてください。このアプローチは、UI をデータ モデルに解釈し、必要に応じて元に戻すために必要なコードが非常に複雑であるため、すべての人に適しているわけではありません。走行距離とニーズは異なる場合があります。これは、それが何を意味するにせよ、合理的な「エンタープライズ」レベルのソリューションの試みです。
HoursOfOperations テーブル
ID | OPEN (分) | CLOSE (分)
1 | 360 | 1020 (例: 午前 9 時~午後 5 時)
2 | 365 | 1021 (例: エッジケース 9:05 AM - 5:01 PM (変人))
等
HoursOfOperations は何日かは気にせず、オープンとクローズと一意性だけです。始値と終値の組み合わせごとに 1 つのエントリしか存在できません。現在、環境に応じて、このテーブル全体をキャッシュするか、1 日の現在の時間などにキャッシュすることができます。とにかく、操作ごとにこのテーブルにクエリを実行する必要はありません。ストレージ ソリューションによっては、このテーブルのすべての列がパフォーマンスのためにインデックス化されていると想定しています。時間が経つにつれて、この表は INSERT の確率が指数関数的に逆になる可能性があります。ただし、実際には、このテーブルの処理はほとんどがインプロセス操作 (RAM) である必要があります。
Business2HoursMap
注: 私の例では、「日」をビット フラグ フィールド/列として格納しています。これは主に、私のニーズと、C# での LINQ / Flags Enums の進歩によるものです。これを 7 ビット フィールドに拡張することを妨げるものは何もありません。どちらのアプローチも、ストレージ ロジックとクエリ アプローチの両方で比較的似ているはずです。
別の注意: 「すべてのテーブルに PK ID 列が必要」というセマンティクスの議論には参加していません。そのための別のフォーラムを見つけてください。
ビジネス ID | 時間 ID | 日 (または、希望する場合は、BIT 月曜日、BIT 火曜日、...)
1 | 1 | 1111111 (このビジネスは毎日 9 時から 5 時まで営業しています)
2 | 2 | 1111110 (このビジネスは 9:05 ~ 5:01 M-Sat (月曜日 = 1 日目) に営業しています)
これが簡単にクエリできる理由は、目的の MOTD (その日の分) をいつでも非常に簡単に判断できるからです。明日の午後 5 時に何が開いているか知りたい場合は、すべての HoursOfOperations IDS WHERE Close >= 1020 を取得します。時間範囲を探していない限り、Open は重要ではありません。次の 30 分以内に閉店するビジネスを表示したくない場合は、それに応じて着信時刻を調整します (午後 5 時 (1020) ではなく、午後 5 時 30 分 (1050) を検索します)。2 番目のクエリは当然 ' HoursID IN (1, 2, 3, 4, 5) などのすべてのビジネスを私に与えてください.このアプローチには制限があるため、これはおそらく警告を発するはずです.しかし,誰かが上記の実際の順列の質問に答えることができれば,私たちはそうするかもしれません.赤旗を引き下げることができます.一度に方程式のいずれかの側で可能な順列のみが必要であると考えてください.
最初のテーブルがキャッシュされていることを考えると、これは簡単な操作です。2 番目の操作では、この潜在的に大きな行のテーブルをクエリしていますが、非常に小さな (SMALLINT) インデックス付きの列を検索しています。
さて、コード側の複雑さを目の当たりにしているかもしれません。私は特定のプロジェクトで主にバーをターゲットにしているので、「午前 11 時から午前 2 時 (翌日)」などの営業時間を持つビジネスがかなりの数あると想定するのは非常に安全です。それは実際、HoursOfOperations テーブルと Business2HoursMap テーブルの両方への 2 つのエントリになります。たとえば、午前 11 時から午前 2 時まで営業しているバーには、HoursOfOperations テーブル 660 から 1440 (午前 11 時から午前 0 時) および 0 から 120 (午前 0 時から午前 2 時) への 2 つの参照があります。これらの参照は、Business2HoursMap テーブルの実際の日数に反映されます。単純なケースでは、1 つのエントリ = 全日の時間参照 #1、別の全日の参照 #2 という 2 つのエントリとして反映されます。それが理にかなっていることを願っています、長い一日でした。
特別な日/休日/何でもオーバーライドします。上書きは本来、日付ベースであり、曜日ベースではありません。これは、いくつかのアプローチが、ことわざの丸いペグを四角い穴に押し込もうとする場所だと思います. 別のテーブルが必要です。
時間 ID | ビジネス ID | 日 | 日 | 月 | 月 | 年
1 | 2 | 1 | 1 | ヌル
「毎週火曜日に、この会社は 4 時間釣りに行く」のようなものが必要な場合、これは確かにより複雑になります。ただし、これにより非常に簡単にできることは、1 - オーバーライドを許可し、2 - 妥当な繰り返しのオーバーライドを許可することです。たとえば、年が NULL の場合、毎年元旦に、この変人バーは上記のデータ例に沿って、午前 9 時から午後 5 時まで営業しています。つまり、年が設定されている場合は、2013 年のみです。月が null の場合は、毎月の最初の日です。繰り返しになりますが、これは NULL 列だけですべてのスケジューリング シナリオを処理できるわけではありませんが、理論的には、必要に応じて絶対日付の長いシーケンスに依存することで、ほぼすべてを処理できます。
繰り返しますが、このテーブルをローリング デイ ベースでキャッシュします。少なくとも私のニーズでは、1 日のスナップショットでこのテーブルの行が非常に大きいことを現実的に見ることはできません。最初にこのテーブルを確認し、オーバーライドして、ストレージ側のはるかに大きな Business2HoursMap テーブルに対してクエリを保存します。
興味深い問題です。これを真剣に考える必要があったのはこれが初めてで、本当に驚いています。いつものように、私のアプローチのさまざまな洞察、アプローチ、または欠陥に非常に熱心です。