如何找到 2 次 SQL 服务器之间的可用或空闲时间段
How to find available or free timeslots between 2 times SQL Server
我有以下 table 结构:
CREATE TABLE [dbo].[ReservationDetails]
(
[SessionID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [bigint] NOT NULL,
[ExpectedStart] [datetime] NOT NULL,
[ExpectedEnd] [datetime] NOT NULL,
CONSTRAINT [PK_dbo.ReservationDetails]
PRIMARY KEY CLUSTERED ([SessionID] ASC)
) ON [PRIMARY]
这是一些数据:
INSERT INTO ReservationDetails (UserID,ExpectedStart,ExpectedEnd)
VALUES (1, '1900-01-01 09:15:00.000', '1900-01-01 09:30:00.000'),
(2, '1900-01-01 10:00:00.000', '1900-01-01 10:30:00.000')
从上面的 table 和数据中,我想找到上午 9 点到 11:30 之间的可用时间段。
这里 UserID = 1
已经预订了从 09:15 上午到 09:30 上午 &
UserID = 2
预订了 10:00 上午到 10:30 上午
的时间
我们需要列出在 09:00 上午到 11:30 上午之间可能的 free/available 时间段。插槽计时没有间隔,我们只需要显示 free/available 计时。
它们如下所示。
09:00 AM TO 09:15 AM
09:30 AM TO 10:00 AM
10:30 AM TO 11:30 AM
我需要帮助才能获得 free/available 个插槽
这是一个间隙和孤岛类型的问题。
请google了解更多。
这是一个example solution:
declare @startTime datetime= '1900-01-01 09:00:00.000', @EndTime datetime='1900-01-01 11:30:00.000';
;
with allts as
(
select top (select datediff(mi,@startTime,@EndTime)+1)
mislot=dateadd(mi,row_number() over(order by (select null))-1,@startTime),
rn=row_number() over(order by (select null))
from
sys.objects t1 cross join
sys.objects t2
),
ts as
( select a.mislot,a.rn, rn2= row_number() over ( order by rn asc)
from allts a
outer apply(
select flag=1 from ReservationDetails r
where a.mislot > ExpectedStart and a.mislot < ExpectedEnd
)b
where b.flag is null
)
select startavl=min(mislot), endavl=max(mislot) from ts
group by rn2-rn
order by startavl asc
对于 c# 中的解决方案,我有以下代码。我没有测试它们。
这个想法是用(持续时间分钟)条目声明一个数组列表。
你有一个对象,在这个对象上你可以阻塞时隙。如果您阻止插槽,阵列列表中的条目将在这一分钟内设置为 false。
要获得空闲时间段,您可以遍历列表。每次如果在 false 之后有 true,你就有空闲槽的开始时间。该槽在下一个 false(空闲槽的结束时间)之前是空闲的。这样您就可以获得免费插槽。
namespace xy
{
class test
{
List<bool> slots = new List<bool>();
DateTime start;
DateTime end;
public test(DateTime start, DateTime end)
{
this.start = start;
this.end = end;
for(int i=1; i <= (end.Hour * 60) + end.Minute; i++)
{
slots.Add(true);
}
}
public void Block_Slots(DateTime startBlock, DateTime endBlock)
{
for(int i = (startBlock.Hour * 60) + startBlock.Minute; i<= (endBlock.Hour * 60) + endBlock.Minute; i++)
{
slots[i] = false;
}
}
public List<Slot> GetFreeSlots()
{
List<Slot> tmp = new List<Slot>();
Nullable<DateTime> startPeriod = null;
Nullable<DateTime> endPeriod = null;
int counter = 1;
foreach(bool entry in slots)
{
if (entry)
{
if(startPeriod == null)
startPeriod = new DateTime(this.start.Year, this.start.Month, this.start.Day, counter / 60 + start.Hour, counter % 60 + start.Minute, 0);
else
{
}
}
else
{
if(startPeriod != null)
{
endPeriod = new DateTime(this.start.Year, this.start.Month, this.start.Day, counter-1 / 60, counter-1 % 60, 0);
tmp.Add(new Slot((DateTime)startPeriod, (DateTime)endPeriod));
startPeriod = null;
endPeriod = null;
}else{}
}
counter++;
}
return tmp;
}
}
class Slot
{
DateTime start;
DateTime end;
public Slot(DateTime start, DateTime end)
{
this.start = start;
this.end = end;
}
}
}
我有以下 table 结构:
CREATE TABLE [dbo].[ReservationDetails]
(
[SessionID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [bigint] NOT NULL,
[ExpectedStart] [datetime] NOT NULL,
[ExpectedEnd] [datetime] NOT NULL,
CONSTRAINT [PK_dbo.ReservationDetails]
PRIMARY KEY CLUSTERED ([SessionID] ASC)
) ON [PRIMARY]
这是一些数据:
INSERT INTO ReservationDetails (UserID,ExpectedStart,ExpectedEnd)
VALUES (1, '1900-01-01 09:15:00.000', '1900-01-01 09:30:00.000'),
(2, '1900-01-01 10:00:00.000', '1900-01-01 10:30:00.000')
从上面的 table 和数据中,我想找到上午 9 点到 11:30 之间的可用时间段。
这里 UserID = 1
已经预订了从 09:15 上午到 09:30 上午 &
UserID = 2
预订了 10:00 上午到 10:30 上午
我们需要列出在 09:00 上午到 11:30 上午之间可能的 free/available 时间段。插槽计时没有间隔,我们只需要显示 free/available 计时。
它们如下所示。
09:00 AM TO 09:15 AM
09:30 AM TO 10:00 AM
10:30 AM TO 11:30 AM
我需要帮助才能获得 free/available 个插槽
这是一个间隙和孤岛类型的问题。
请google了解更多。
这是一个example solution:
declare @startTime datetime= '1900-01-01 09:00:00.000', @EndTime datetime='1900-01-01 11:30:00.000';
;
with allts as
(
select top (select datediff(mi,@startTime,@EndTime)+1)
mislot=dateadd(mi,row_number() over(order by (select null))-1,@startTime),
rn=row_number() over(order by (select null))
from
sys.objects t1 cross join
sys.objects t2
),
ts as
( select a.mislot,a.rn, rn2= row_number() over ( order by rn asc)
from allts a
outer apply(
select flag=1 from ReservationDetails r
where a.mislot > ExpectedStart and a.mislot < ExpectedEnd
)b
where b.flag is null
)
select startavl=min(mislot), endavl=max(mislot) from ts
group by rn2-rn
order by startavl asc
对于 c# 中的解决方案,我有以下代码。我没有测试它们。 这个想法是用(持续时间分钟)条目声明一个数组列表。 你有一个对象,在这个对象上你可以阻塞时隙。如果您阻止插槽,阵列列表中的条目将在这一分钟内设置为 false。 要获得空闲时间段,您可以遍历列表。每次如果在 false 之后有 true,你就有空闲槽的开始时间。该槽在下一个 false(空闲槽的结束时间)之前是空闲的。这样您就可以获得免费插槽。
namespace xy
{
class test
{
List<bool> slots = new List<bool>();
DateTime start;
DateTime end;
public test(DateTime start, DateTime end)
{
this.start = start;
this.end = end;
for(int i=1; i <= (end.Hour * 60) + end.Minute; i++)
{
slots.Add(true);
}
}
public void Block_Slots(DateTime startBlock, DateTime endBlock)
{
for(int i = (startBlock.Hour * 60) + startBlock.Minute; i<= (endBlock.Hour * 60) + endBlock.Minute; i++)
{
slots[i] = false;
}
}
public List<Slot> GetFreeSlots()
{
List<Slot> tmp = new List<Slot>();
Nullable<DateTime> startPeriod = null;
Nullable<DateTime> endPeriod = null;
int counter = 1;
foreach(bool entry in slots)
{
if (entry)
{
if(startPeriod == null)
startPeriod = new DateTime(this.start.Year, this.start.Month, this.start.Day, counter / 60 + start.Hour, counter % 60 + start.Minute, 0);
else
{
}
}
else
{
if(startPeriod != null)
{
endPeriod = new DateTime(this.start.Year, this.start.Month, this.start.Day, counter-1 / 60, counter-1 % 60, 0);
tmp.Add(new Slot((DateTime)startPeriod, (DateTime)endPeriod));
startPeriod = null;
endPeriod = null;
}else{}
}
counter++;
}
return tmp;
}
}
class Slot
{
DateTime start;
DateTime end;
public Slot(DateTime start, DateTime end)
{
this.start = start;
this.end = end;
}
}
}