1

私は単純なデータベースを持っており、予約およびスケジューリング システムを作成したいと考えています。私の目標を達成するために変更することは自由ですので、必要に応じてデザインを変更することを心配しないでください.

以下は ERD です。

ここに画像の説明を入力

問題は次のとおりです。 特定の時間 (予約期間) に特定の場所 (予約可能エリア) に予約できるメンバーがいます。現在の関係セットでは、多くのメンバーが多くの場所で何度も予約することができ、これらが重複する可能性があります。つまり、ダブルブッキングや、同時に 2 つの場所を予約する (つまり、同時に 2 つの場所にいる) ことができます。

私の質問は、次のことを厳密に許可するようにこのデータベースの設計を変更するにはどうすればよいですか?など)。メンバーが 1 つの場所と時間を効果的に予約できるようにします。一度予約すると、他のメンバーが同じ場所と時間を予約することはできません。同じ場所を別の時間に予約することも、同時に別の場所を予約することもできますが、両方を予約することはできません。

これを実現するには、何を変更する必要がありますか。リレーションシップでそれを行うことは明らかなので、リレーションシップで行うことをお勧めしますが、最後の手段として、リレーションシップを使用してそれを行う方法がない場合は、トリガーを使用しますが、トリガーではないため使用したくありませんオタクと同じくらい明白です。

助けてくれてありがとう。

編集 1: トリガーとチェック制約は確かに答えとして受け入れられます。これが標準ではないとか、間違っているとは決して言いません。これしか方法がないなら、こうするしかない。ただし、これが事実であることを他のプログラマーにできるだけ明確にしたいので、私は尋ねています。これが、関係を通じてそれを行う方法を探している理由です。ただし、これが不可能な場合があることは承知しています。確かにわからないので、質問です。

編集2:制約やトリガーを使用せずにやりたいと言ったことは知っていますが、物事を過度に複雑にする極端な手段なしではこれを行うことはできないようです. しかし、人間関係に関するいくつかの本当に素晴らしい考えを示しているので、私は複雑すぎる答えが好きです. みんな、ありがとう。

4

3 に答える 3

1

元の応答

私が正しく理解している場合、次のシナリオは、許可されているものと許可されていないものの例を示しています。

Member            Book Time              Book Place
-----------------------------------------------------
John              0900-1000              Room 1
John              1000-1100              Room 1
John              1100-1200              Room 1
John              0900-1000              Room 2        <--- not allowed, member double booked
Jane              0900-1000              Room 1        <--- not allowed, room double booked

したがって、強制したいのは、2つの別々のグループの一意性です。1つのグループはメンバーとブックタイムで、もう1つのグループはブックタイムとブックプレイスです。

Bookingsこれらの列を使用してに2つの一意のキーを作成し、どちらのグループも複製できないようにすることができます。つまり、ブックタイムが重複しているメンバーは、一意の制約に違反するため繰り返すことができず、ブックプレイスが重複しているブックタイムは同じ理由で繰り返すことができません。

編集:あなたはこのシナリオの制約に完全に反対しているようですので、私の答えは無意味かもしれません。

EDIT2:私のソリューションは、テーブルの主キーとして代理キーを確立することを前提としていBookingsます。それについて言及しなかったことをお詫びします。

代替オプション

これが私が考えた奇抜なアイデアです。6つのテーブルを維持できます。

Member
BookTime
BookPlace
Member_BookTime
BookPlace_BookTime
Member_BookTime_BookTime_BookPlace

OK、あなたが私を書き留める前に、ただ私を聞いてください!ダイアグラムには、これらのテーブルの4/6があります。メンバー、BookTimes、BookPlacesの関係を分割することを提案しています。

以下に、代理の主キーと複合一意キーがあり、メンバーが一時的に二重予約されないことを保証します。

Member_BookTime
---------------
ID (PK)
Member_ID (CUK)
BookTime_ID (CUK)

そして、以下には代理主キーと複合一意キーがあり、一時的に部屋が二重に予約されていないことを保証します。

BookPlace_BookTime_ID
------------------
ID (PK)
BookPlace_ID (CUK)
BookTime_ID (CUK)

以下に、複合主キーと、メンバーの予約時間と部屋の予約時間の関係を示し、最終的にメンバーを特定の時間部屋に結び付けます。

Member_BookTime_BookTime_BookPlace
----------------------------------
Member_BookTime_ID (CPK)
BookPlace_BookTime_ID (CPK)

それは意味がありますか?上記のスキーマでは、メンバーは二重予約できず、部屋は二重予約できません。それは「過剰正規化」かもしれないと思いますが、それは関係をもう少し明確にします。

提案された制約は、テーブルの定義に使用されるSQLに表示されるため、実際には「非表示」ではありません。データの制約に関するすべてをERDから見えるようにしたいことは理解していますが、制約が複雑すぎる場合があります。

于 2012-07-30T17:15:25.143 に答える
1

30 分または 15 分間隔のみをサポートしたい場合は、以下のようにすることができます。

期間テーブルは次のようになります。

   ID     StartPeriod End Period
   1      0:00        0:15
   2      0:15        0:30 
   3      0:30        0:45 
   4      0:45        1:00 
   5      1:00        1:15

*など

したがって、メンバー 1 が 2012 年 7 月 30 日の午前 0 時から午前 12 時 30 分までエリア 1 を予約し、予約の説明が「睡眠」である場合、レコードは次のようになります。

    BookingInfo
    Id    Description
    1     "Sleep"

    Bookings
    Id     MemberId PeriodID BookingInfoId BookableAreaId Day
    1      1        1        1             1              7/30/2012
    2      1        2        1             1              7/30/2012

次に、MemberId、Day、PeriodId を持つ Bookings に 2 つの Unique インデックスを配置できます (これにより、それらが同じ日に同時にスケジュールされるのを防ぐことができます)。

もう 1 つは BookableAreaId、Day、PeriodId 用です (これにより、誰かが同じ日に同じ 15 分間隔で同じエリアを二重予約することを防止できます)。

また、Id フィールドを Bookings テーブルの主キーとして削除し、Unique インデックスの 1 つをそれらのフィールドの主キーに置き換えることもできます。

あいまいなフォーマットで申し訳ありませんが、私はこのサイトを初めて使用しています。写真を投稿できないため、ERDをリンクとして添付します(十分な担当者が得られるまで)

ERD

于 2012-07-30T17:32:34.253 に答える
1

次のようにデータモデルを変更します。

BookingPeriods にはタイムスロットのリストが含まれます。例えば。午前と午後で予約できます。この場合、StartTime は午前 9 時、EndTime は午後 1 時になります。または、1 時間単位で、つまり午前 9 時から午前 10 時、午前 10 時から午前 11 時などを記録します。

Create table BookingPeriods (
    id int primary key
  , StartTime Time
  , EndTime Time
  , Description varchar(max)
)

BookingAvailability は、タイムスロットと日付の間の単純なマッピングになります。したがって、可能なタイムスロットの日付ごとのリストがあります

Create table BookingAvailability(
    id int primary key
  , Day Date
  , PeriodId int references BookingPeriods(id)
    constraint uq_bookingAvailability unique (Day, PeriodId)
)

BookableAreas は物理的な場所のリストになります。

Create table BookableAreas(
    id int primary key
  , Name varchar(100)
  , ActivityTypeId int
  , Description varchar(max)
)

メンバーはそのまま

Create table Members(
    id int primary key
  , FirstName varchar(100)
  , ...
 )

次に、予約はすべてが集まるテーブルになります。可用性レコードとエリアごとに一意のレコードを作成します。memberid は、レコードの単なる補足情報です。

Create table Bookings(
    id int primary key
  , AvailabilityId int references BookingAvailability(id)
  , AreaId int references BookableAreas(id)
  , MemberId int references Members(id)
    constraint uq_Bookings unique (AvailabilityId, AreaId)
)

このデータ モデルは、次のように使用されます。

ここでタイムスロットに「オーバーラップ」を登録しないようにしてください。より細かい詳細が必要な場合は、たとえば 1 時間ごとにレコードを作成する必要があります。

INSERT INTO BookingPeriods (id, StartTime, EndTime, Description)
VALUES (1, '9:00 AM', '12:00 AM', 'Morning'), 
       (2, '1:00 PM', '4:00 PM', 'Afternoon')

これは、予約可能な時間帯のリストです。(例: 週末の日付は除外されます)

INSERT INTO BookingAvailability(id, [Day], PeriodId)
VALUES (1, '20120801', 1),
       (2, '20120801', 2),
       (3, '20120801', 1),
       (4, '20120801', 2),
       (5, '20120801', 1),
       (6, '20120801', 2)

INSERT INTO BookableAreas (id, Name, ActivityTypeId, Description)
VALUES (1, 'Ground Floor', 1, 'The ground floor room'),
       (2, 'East Wing Room', 1, 'The east wing room on the first floor'),
       (3, 'West Wing Room', 1, 'The west wing room on the first floor')

INSERT INTO Members(id, FirstName)
VALUES (1, 'Barak'),
       (2, 'Tony'),
       (3, 'George')

ここでは、実際の予約を作成しようとします。

INSERT INTO Bookings(id, AvailabilityId, AreaId, MemberId)
VALUES (1, 3, 1, 1) -- Barak books the ground floor on 20120801 in the morning

INSERT INTO Bookings(id, AvailabilityId, AreaId, MemberId)
VALUES (2, 3, 1, 2)  -- Tony books the ground floor on 20120801 in the morning --> error

INSERT INTO Bookings(id, AvailabilityId, AreaId, MemberId)
VALUES (2, 4, 1, 2)  -- Tony books the ground floor on 20120801 in the afternoon --> ok
于 2012-07-30T17:37:10.387 に答える