-1

私はクラスの内部申し込みフォームに取り組んでいます。ユーザーがスケジュールが競合するクラスを選択したかどうかを確認する簡単な関数に取り組んでいます(たとえば、午後1時から2時までのクラスと、同じ日の午後1時から3時までのクラス)。

mysqliユーザーが開始フィールドと終了フィールドを持つMySQLテーブルから選択したクラスを使用およびフェッチしていると仮定するとdatetime、複数のクラスを比較して競合するかどうかを確認するための最も効率的および/または効果的な方法は何ですか?

編集:ここにサンプルテーブルがあります:

====================================================
|  id  |        start        |         end         | 
====================================================
|  1   | 2012-10-01 08:00:00 | 2012-10-01 08:00:00 |
====================================================

もちろん、表には他のデータ(タイトル、説明など)がありますが、比較を行うために必要なのは上記のデータだけだと思います。idユーザーがサインアップしたすべてのクラスの配列があります。

これが重複している場合は申し訳ありませんが、検索を行いましたが、これまでに尋ねられたものは表示されませんでした。

4

1 に答える 1

0

このテーブルの主キーが何であるかわかりません。私はあなたにとって私のものが間違っているとかなり確信していますが、あなたの質問の目的にとっては問題ではないはずです。

-- student_id and class_id are foreign keys, not shown
create table times (
  student_id integer not null,
  class_id integer not null,
  primary key (student_id, class_id), 

  start_time timestamp not null,
  end_time timestamp not null
);

最初の生徒はクラス2とクラス3の間に重複があります。

insert into times values
(1, 1, '2012-09-01 08:00', '2012-09-01 08:55'),
(1, 2, '2012-09-01 10:00', '2012-09-01 11:55'),
(1, 3, '2012-09-01 11:45', '2012-09-01 12:45');

2番目の学生、重複はありません。

insert into times values
(2, 1, '2012-09-01 08:00', '2012-09-01 08:55'),
(2, 2, '2012-09-01 10:00', '2012-09-01 11:55');

3番目の生徒はクラス1と2の間に重複があります。

insert into times values
(3, 1, '2012-09-01 08:00', '2012-09-01 10:00'),
(3, 2, '2012-09-01 09:55', '2012-09-01 11:55'),
(3, 3, '2012-09-01 12:00', '2012-09-01 12:55');

プラットフォームがSQL-92に準拠している場合は、OVERLAPS演算子を使用できます。(dbmsがアサーションをサポートしている場合は、重複するクラスを挿入できないようにテーブルを宣言できます。)

select t1.*
from times t1
inner join times t2 on t1.student_id = t2.student_id
       and (t1.class_id <> t2.class_id and t1.start_time <> t2.start_time and t1.end_time <> t2.end_time )
       and (t1.start_time, t1.end_time) overlaps (t2.start_time, t2.end_time);

MySQLはそれをサポートしていないようです。そのため、SQL標準委員会の同等の定義を使用できます。

select t1.*
from times t1
inner join times t2 on t1.student_id = t2.student_id
       and (t1.class_id <> t2.class_id and t1.start_time <> t2.start_time and t1.end_time <> t2.end_time )
       and (
             (t1.start_time > t2.start_time and not (t1.start_time >= t2.end_time and t1.end_time >= t2.end_time))
             or
             (t2.start_time > t1.start_time and not (t2.start_time >= t1.end_time and t2.end_time >= t1.end_time))
             or
             (t1.start_time = t2.start_time and (t1.end_time <> t2.end_time or t1.end_time = t2.end_time))
       );

テーブルに注意深くインデックスが付けられている限り、結合条件によって優れたパフォーマンスが得られると思います。あなたの場合、あなたは一人の学生のために行を選択するでしょう、それはかなり選択的であるべきです。(サンプルコードではそれをしませんでした。)

于 2012-08-20T02:38:15.633 に答える