2009-07-06 18 views
2

我有三張桌子。按時間查找可用性

  • 表(t)是我係統中的一個資源。 它有一個最大容量。
  • 預訂(B),在 系統保留,它長谷FromDatimeTime, ToDateTime和nrOfPeople
  • BookedTable(BT),連接 預訂的桌子和有多少個座位 受此預訂時使用,一 預訂可以有多個表。

的問題是,如果我有三個訂單:

  1. 4人在12點 在正在添加離開14:00。
  2. 4人12:00和 在13:00離開。
  3. 4人13:00起牀, 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個或更多預訂在同一張桌子上分享時間。

我不想訴諸於預訂過程中所有可能的時間循環,並檢查是否超額預訂。 查詢經常使用,也許每分鐘一次,所有用戶每天可能會有幾百行。 我可以使用SQL或Delphi數據集(但我寧願做在SQL)

編輯1

這是一個較大的存儲過程,做所有類型的其他的東西的一部分,所以它可能是一個功能。

我寧願我不必處理最小間隔。 大多數使用該產品的客戶都不存在此問題,因爲他們不允許分割表格。我不希望查詢對他們顯着慢。

+0

你所關心的最小間隔是多少?小時,半小時還是分鐘? – 2009-07-06 15:37:40

+0

解決方案是否可以選擇存儲過程?還是它必須是單個SQL選擇? – 2009-07-07 06:44:56

回答

2

訣竅是在子查詢/ derrived/CTE中展開您的「預訂」表,因此每隔「間隔」(小時/半小時/分鐘/等)是一行,那麼您可以SUM - GROUP BY - HAVING SUM()> limit。您可以使用Numbers表來展開預訂表。

編輯的代碼你的問題建表,如:

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

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

,所以我可以嘗試一個或兩個查詢,我想嘗試寫你...

編輯

要低於使用我的查詢,你需要創建這個表:

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?