Sql server 按时间查找可用性
我有三张桌子Sql server 按时间查找可用性,sql-server,delphi,datetime,Sql Server,Delphi,Datetime,我有三张桌子 表(t),我的系统中的一个资源。 它有最大容量 预订(b),在 系统,它从DATIMETIME开始, 当今时代和人们的生活 BookedTable(bt),连接 用桌子预订,有多少座位 此预订使用的,a 预订可以有多张桌子 问题是,如果我有三个预订: 4人在12:00和 14点出发 4人在12:00和 13点出发 4人在13:00和 14点出发 所有预订使用同一张桌子,共有8个座位。 我想知道这张桌子是否“超额预定” 设置代码 CREATE TABLE Tables (
- 表(t),我的系统中的一个资源。 它有最大容量
- 预订(b),在 系统,它从DATIMETIME开始, 当今时代和人们的生活
- BookedTable(bt),连接 用桌子预订,有多少座位 此预订使用的,a 预订可以有多张桌子
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]
选择Booking.BookingNr,[Booking].[Time\u From],[Booking].[Time\u TO],[Booking].[Guests],[Tables].TableNr,
当[表格][座位]出现时的情况-
(从[Table_Booking]中选择sum(tbInner.[GuestOnTable])作为tbInner
在bInner.BookingNr=tbInner.BookingNr上以bInner的身份加入[预订]
其中(不是(Booking.Time\u From>=bInner.[Time\u To]或bInner.[Time\u From]>=Booking.Time\u To))
)<0然后“超额预订”,否则“正常”结束为TableStatus
来自[预订]
在[Booking].[BookingNr]=[Table\u Booking].[BookingNr]上加入[Table\u Booking]
在[Tables].[TableNr]=[Table\u Booking].[TableNr]上加入[Tables]
给我:
预订数量1=超额预订
预订2和3=可以
如果我取消预订3。我得到了预期的结果。问题是当3个或更多预订共享同一张桌子上的时间时
我不想求助于像在预订期间在所有可能的时间做一个循环,并检查是否超额预订。
查询经常被使用,所有用户可能每分钟使用一次,一天可能有几百行。
我可以使用SQL或delphi数据集(但我更愿意使用SQL)
编辑1
它是一个更大的存储过程的一部分,它可以处理所有其他的事情,所以它可以是一个函数
我宁愿我不需要处理最小间隔。
大多数使用该产品的客户没有这个问题,因为他们不允许拆分表。我不想让他们的查询速度明显变慢 诀窍是在子查询/derrived/CTE中展开“Booking”表,因此每“interval”(小时/半小时/分钟/等)一行,然后您可以通过-HAVING SUM()>limit对-GROUP进行求和。您可以使用数字表展开bookings表 使用代码编辑您的问题以生成表格,如:
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 @x=@x+1
INSERT INTO Numbers VALUES (@x)
END
创建表编号
(数字int不为空,
约束主键聚集(数字ASC)主键,并在[主]上(PAD_INDEX=OFF,STATISTICS_norecocomputer=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON)
)在[小学]
声明@x int
设置为@x=0
而@x您关心的最小间隔是多少?小时、半小时或分钟?解决方案可以是可选的存储过程吗?或者它必须是一个单一的SQL选择?这让我朝着正确的方向前进。我最终解决了这个问题。我所做的主要区别在于,我使用了一个带有可能时间的临时选项卡,而不是在实际查询中使用“DateAdd”。这是由于系统中的其他设计。
--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