0

MySQLの予約システムで作業していますが、次に利用可能な予約枠を見つけるためのクエリで少し問題が発生しています。

私の日は15分のスロットに分けられます(00:00:00〜00:14:59、00:15:00〜00:29:59など)。これまでのテーブル構造:

予定表:

CREATE TABLE IF NOT EXISTS `appointments` (
`appointmentID` int(9) unsigned NOT NULL AUTO_INCREMENT,
`patientID` int(9) unsigned NOT NULL,
`apptTitle` varchar(50) NOT NULL,
`apptDT` datetime NOT NULL,
`apptLength` int(4) NOT NULL,
`apptStatus` varchar(25) NOT NULL,
`physician` int(9) unsigned NOT NULL,
`apptType` varchar(30) NOT NULL,
`apptLocation` varchar(25) NOT NULL,
PRIMARY KEY (`appointmentID`),
KEY `patientID` (`patientID`),
KEY `physician` (`physician`),
KEY `apptStatus` (`apptStatus`),
KEY `apptLocation` (`apptLocation`),
KEY `apptType` (`apptType`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

apptSlotsテーブル:

CREATE TABLE IF NOT EXISTS `apptSlots` (
`startDT` datetime NOT NULL,
`endDT` datetime NOT NULL,
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

上で説明したように、apptSlotsテーブルは2012年の15分のスロットすべてですでに埋められています。

まったく使用されていない(予定がまったくスケジュールされていない)スロットを正常に表示できるクエリがあります。

SELECT a.*
FROM apptSlots AS a
LEFT JOIN appointments AS b
ON a.endDT
BETWEEN b.apptDT AND DATE_ADD(b.apptDT, INTERVAL b.apptLength MINUTE)
AND b.appointmentID IS NULL

ここで行う必要があるのは、複数の医師、複数の部屋などで予約枠を検索することです。たとえば、医師Aが午前7時から午前8時までの予約をした場合、その時間枠は上記のクエリに表示されなくなります。しかし、医師BとCにはそのスロットの予定がないので、それらをスケジュールできるようにする必要があります。同じことが部屋にも当てはまります。部屋Aは午前7時の予定で使用されますが、部屋BとCは引き続き自由にスケジュールできます。

これらすべての変数で空きスロットを決定するにはどうすればよいですか?私は、各組み合わせのWHERE条件でテストできることを知っています。これは、特定の医師または治療のための特定の部屋をテストする必要がある場合に機能します。しかし、すべての医師と部屋のすべてのスロットを表示したいだけの場合、クエリは機能せず、すべての可能な組み合わせを個別にテストすることは正しくないようです。LEFTJOIN句に適切な条件を設定する方法の問題です。 。

不明な点がありましたらお知らせください。十分な情報だと思います。そうでない場合は、あなたが求めるものは何でも追加します!

あなたの助けに感謝します、ここでの私の前の質問は上記の私の質問まで私を手に入れました、今私はいくつかの改良が必要です。あなたが必要とするどんな質問でもしてください、私は彼らに答えるためにここにいます!

4

2 に答える 2

2

リクエストに応じて、さまざまなコメントからまとめた回答を次に示します。

アポイントメントスロット用にテーブルを1つだけ持つことはできないことに注意してください。各医師は、休暇などを含む異なるスケジュールを持ちます。doctor_idは、available_appointmentsテーブルの一部である必要があります。

また、予約室やポータブル機器などの「リソース」もあります。これらは、独自の可用性とスケジュールを使用して、別のテーブル(available_resources?)に配置する必要があります。

時間のブロックを見つけることに関しては、これを試してください:

set @last_time = null;
set @block_size = 1;

select *
from (
  select startDT,
    case when @last_time is null or startDT = date_add(@last_time, interval 15 minute)
      then @block_size := @block_size + 1
      else @block_size := 1
    end as block_size,
    @last_time := startDT
  from foo_appt
) foo
where block_size = 4;

編集:

これが私のテストデータです:

+---------------------+
| startDT             |
+---------------------+
| 2012-11-06 13:00:00 |
| 2012-11-06 13:15:00 |
| 2012-11-06 14:00:00 |
| 2012-11-06 14:15:00 |
| 2012-11-06 14:30:00 |
| 2012-11-06 14:45:00 |
| 2012-11-06 16:00:00 |
| 2012-11-06 16:15:00 |
+---------------------+

つまり、30分のブロック、1時間のブロック、さらに30分のブロックがあります。

内部クエリは手間のかかる作業を行い、次の出力を生成します。最後の2つの列は、2つの変数を維持するためのものであり、無視する必要があります。

+---------------------+------------+-------------+-----------------------+
| startDT             | block_size | @block_size | @last_time := startDT |
+---------------------+------------+-------------+-----------------------+
| 2012-11-06 13:00:00 |          1 |           1 | 2012-11-06 13:00:00   |
| 2012-11-06 13:15:00 |          2 |           2 | 2012-11-06 13:15:00   |
| 2012-11-06 14:00:00 |          1 |           1 | 2012-11-06 14:00:00   |
| 2012-11-06 14:15:00 |          2 |           2 | 2012-11-06 14:15:00   |
| 2012-11-06 14:30:00 |          3 |           3 | 2012-11-06 14:30:00   |
| 2012-11-06 14:45:00 |          4 |           4 | 2012-11-06 14:45:00   |
| 2012-11-06 16:00:00 |          1 |           1 | 2012-11-06 16:00:00   |
| 2012-11-06 16:15:00 |          2 |           2 | 2012-11-06 16:15:00   |
+---------------------+------------+-------------+-----------------------+

外部クエリを使用すると、適切なblock_sizeを持つクエリだけを取得できます。4番目のブロックの開始時刻を取得しています。

MySQLでは、クエリで一度に複数の変数を設定することはできません(プロシージャで設定する必要があります)。これは、このように混乱させようとするとがっかりします。

頭に浮かぶ最も簡単なことは、4番目の期間を取り、最初の期間の開始に戻すことです。したがって、外部クエリは次のようになります。

select date_sub(startDT, interval 15 * (block_size-1) minute) as appointment_time,
    block_size*15 as appointment_duration
from ( ...

+---------------------+----------------------+
| appointment_time    | appointment_duration |
+---------------------+----------------------+
| 2012-11-06 14:00:00 |                   60 |
+---------------------+----------------------+

お役に立てば幸いです。

于 2012-11-06T17:36:18.717 に答える
0

これを試して。あなたが医師のテーブルを持っていると仮定すると、これでうまくいくはずだと思います。

SELECT  a.* 

FROM    apptSlots AS a 

        CROSS JOIN employees p 

        LEFT JOIN appointments AS b 
        ON p.employeeID = b.physician 
        AND a.endDT BETWEEN b.apptDT AND DATE_ADD(b.apptDT, INTERVAL b.apptLength MINUTE)

WHERE   b.appointmentID IS NULL
于 2012-11-05T20:18:29.027 に答える