2009-07-06 5 views
2

私は3つのテーブルを持っています。時間で空室を見つける

  • 私のシステムのリソースである表(t)。 最大容量です。
  • 予約(b)は、 システムにおける予約、それは
  • BookedTable(BT)、テーブルを用いて、どのように多くの座席この予約によって使用さ 、 予約を接続FromDatimeTime、 ToDateTimeとnrOfPeopleをHASE 予約は複数のテーブルを持つことができます。

問題は、私は3件の予約がある場合:14:00に残し12:00 で来

  1. 4人を。
  2. 4人が12:00に来て、 が13:00に出発します。
  3. 13:00に来ている4人と、14:00に残している 。

すべての予約は8席の同じテーブルを使用しています。 テーブルが "オーバーブッキング"されている場合は、私はしたい。

セットアップコード

CREATE TABLE Tables (
     TableNr INT, 
     Seats INT 
     ) 
GO 
CREATE TABLE Booking 
    ( 
    BookingNr INT, 
    Time_From DATETIME, 
    Time_TO DATETIME, 
    Guests INT 
    ) 
GO 
CREATE TABLE Table_Booking  
(
TableBookingId INT , 
BookingNr INT , 
TableNr INT , 
GuestOnTable int 
) 
GO 
INSERT INTO [Tables] ( [TableNr], [Seats]) VALUES (1, 8) 
INSERT INTO [Tables] ( [TableNr], [Seats]) VALUES (2, 4) 
INSERT INTO [Tables] ( [TableNr], [Seats]) VALUES (3, 4) 

INSERT INTO [Booking] ([BookingNr],[Time_From],[Time_TO],[Guests]) VALUES (/* BookingNr - INT */ 1,/* Time_From - DATETIME */ '2009-7-7 11:00',/* Time_TO - DATETIME */ '2009-7-7 13:00',/* Guests - INT */ 4) 
INSERT INTO [Booking] ([BookingNr],[Time_From],[Time_TO],[Guests]) VALUES (/* BookingNr - INT */ 2,/* Time_From - DATETIME */ '2009-7-7 11:00',/* Time_TO - DATETIME */ '2009-7-7 12:00',/* Guests - INT */ 4) 
INSERT INTO [Booking] ([BookingNr],[Time_From],[Time_TO],[Guests]) VALUES (/* BookingNr - INT */ 3,/* Time_From - DATETIME */ '2009-7-7 12:00',/* Time_TO - DATETIME */ '2009-7-7 13:00',/* Guests - INT */ 4) 


INSERT INTO [Table_Booking] ([TableBookingId],[BookingNr],[TableNr], GuestOnTable) VALUES (/* TableBookingId - INT */ 1, /* BookingNr - INT */ 1,/* TableNr - INT */ 1, 4) 
INSERT INTO [Table_Booking] ([TableBookingId],[BookingNr],[TableNr], GuestOnTable) VALUES (/* TableBookingId - INT */ 2, /* BookingNr - INT */ 2,/* TableNr - INT */ 1, 4) 
INSERT INTO [Table_Booking] ([TableBookingId],[BookingNr],[TableNr], GuestOnTable) VALUES (/* TableBookingId - INT */ 3, /* BookingNr - INT */ 3,/* TableNr - INT */ 1, 4) 

GO 

簡単なテストクエリ

select Booking.BookingNr, [Booking].[Time_From], [Booking].[Time_TO], [Booking].[Guests], [Tables].TableNr , 
    CASE WHEN [Tables].[Seats] - 
    ( select sum(tbInner.[GuestOnTable]) from [Table_Booking] as tbInner  
     join [Booking] AS bInner on bInner.BookingNr = tbInner.BookingNr 
     where (NOT (Booking.Time_From>= bInner.[Time_To] OR bInner.[Time_From] >= Booking.Time_To)) 
     ) < 0 THEN 'OverBooked' ELSE 'Ok' END AS TableStatus 
     from [Booking] 
     join [Table_Booking] on [Booking].[BookingNr] = [Table_Booking].[BookingNr] 
     join [Tables] on [Tables].[TableNr] = [Table_Booking].[TableNr] 

は私を与える: Bookingnr 1 =は、予約2及び3 = OK をオーバーブッキング。

予約を削除した場合3.期待通りの結果が得られます。問題は、3つ以上の予約が同じテーブルで時間を共有する場合です。

私は、予約時にすべての可能な時間にわたってループを行い、予約がオーバーブッキングされているかどうかをチェックするようなものに頼らず、 クエリは頻繁に使用されます。1分に1回、すべてのユーザーが1日に数百の行を使用できます。 私は、

編集1

は、それが他のもののすべての種類を行い、より大きなストアドプロシージャの一部である(しかし、私はむしろSQLでそれを行うだろう)、SQLやDelphiのデータセットのいずれかを使用することができますそれは関数である可能性があります。

私は分間隔で対処しなければならないと思います。 製品を使用しているほとんどのお客様は、テーブルの分割を許可していないため、この問題は発生しません。そして私はそれらのクエリが大幅に遅くなることを望んでいません。

+0

あなたが関係する最小間隔はどれくらいですか?時間、分、または分ですか? –

+0

解決策は選択可能なストアドプロシージャである可能性がありますか?それとも、単一のSQL selectでなければならないのですか? –

答えて

2

サブクエリ/ derrived/CTEの "Booking"テーブルを拡張することで、 "interval"(時間/半時間/分/など)あたり1行になるので、SUM-GROUP SUM()> limitを持つ。 Numbersテーブルを使用して予約テーブルを展開します。

編集のようなテーブル、構築するためのコードをあなたの質問:

DECLARE @t table (col1...... ) 
INSERT into @t values (...... 

DECLARE @Booking table(.... 
INSERT into @Bookings) values (..... 

ので、私は、クエリまたは2を試してみることができ、私はあなたのためにそれを書くために試してみたが...

以下の私のクエリを使用するには、[編集]

、あなたがこのテーブルを作成する必要があります。

CREATE TABLE Numbers 
(Number int NOT NULL, 
    CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
DECLARE @x int 
SET @x=0 
WHILE @x<8000 
BEGIN 
    SET @[email protected]+1 
    INSERT INTO Numbers VALUES (@x) 
END 

は、ここでいくつかのクエリです:

--get one row per time "interval" (hour) per booking 
SELECT 
    b.BookingNr, b.Time_From, b.Time_TO, b.Guests 
     ,DATEADD(hh,Number-1,b.Time_From) AS ActualTime 
    FROM Booking   b 
     INNER JOIN Numbers n ON DATEADD(hh,Number-1,b.Time_From)<=Time_TO 
    ORDER BY 1,5 

--get one row per time "interval" (hour), combining each interval 
SELECT 
    bt.TableNr, SUM(b.Guests) AS TotalGuests 
     ,DATEADD(hh,Number-1,b.Time_From) AS ActualTime 
    FROM Booking     b 
     INNER JOIN Numbers   n ON DATEADD(hh,Number-1,b.Time_From)<=Time_TO 
     INNER JOIN Table_Booking bt ON b.BookingNr=bt.BookingNr 
    GROUP BY bt.TableNr, DATEADD(hh,Number-1,b.Time_From) 
    ORDER BY 3 

--get one row per time "interval" (hour), where the seat limit was exceeded 
SELECT 
    bt.TableNr, SUM(b.Guests) AS TotalGuests 
     ,DATEADD(hh,Number-1,b.Time_From) AS ActualTime 
     ,t.Seats-SUM(b.Guests) AS SeatsAvailable 
    FROM Booking     b 
     INNER JOIN Numbers   n ON DATEADD(hh,Number-1,b.Time_From)<=Time_TO 
     INNER JOIN Table_Booking bt ON b.BookingNr=bt.BookingNr 
     INNER JOIN Tables   t ON bt.TableNr=t.TableNr 
    GROUP BY bt.TableNr,t.Seats, DATEADD(hh,Number-1,b.Time_From) 
    HAVING SUM(b.Guests)>t.Seats 
    ORDER BY 3 

私はあなたが座席の制限を超えたときにどのように処理するかわかりません。これらのクエリでは十分でない場合は、何が必要なのか教えてください...また、どのバージョンのSQL Serverを使用していますか?

+0

これは正しい方向に私を得た。そして、私は結局その問題を解決しました。主な違いは、実際のクエリで「DateAdd」を使用するのではなく、可能な時間で一時的なテーブルを使用したことでした。それはシステム内の他の設計によるものです。 –

関連する問題