如果不同的事件可以重叠,跨越多天,在间隔之前开始,在间隔之后结束,那么找到在给定时间间隔内没有事件的日期的最佳方法是什么。
即:
event start end
e1 01/01/2009 02/01/2009
e2 01/15/2009 01/31/2009
e3 08/15/2008 01/16/2009
e4 02/03/2009 02/15/2009
根据该数据我们可以看到2009年2月2日没有事件。
答案 0 :(得分:1)
虽然这不受时间间隔的限制,但这将为您提供 事件中的所有可用空白:
declare @temp table (evt varchar(10), start datetime, [end] datetime)
insert into @temp values('e1', '1/1/2009', '2/1/2009')
insert into @temp values('e2', '1/15/2009', '1/31/2009')
insert into @temp values('e3', '8/15/2008', '1/16/2009')
insert into @temp values('e4', '2/3/2009', '2/15/2009');
with NextEvent as (select
t.evt,
tafter.evt nextEvt,
tafter.start start,
tafter.[end] [end],
ROW_NUMBER() over (order by t.evt, tafter.start) - RANK() over (order by t.evt) as number
from @temp t
left join @temp tafter on tafter.[end] >= t.[end] and tafter.evt <> t.evt)
select
t.evt,
t.start,
t.[end],
ne.nextEvt [next],
ne.start,
ne.[end]
from @temp t
left join NextEvent ne on ne.evt = t.evt and ne.number = 0
where ne.start > t.[end]
答案 1 :(得分:0)
我不确定我理解你的问题。对于给定日期,您希望查看返回的行数(事件)?
所以对于2/1/09你应该看到1,对于2/2/09你应该看到0 ??? SQL:
declare @temp table (evt varchar(10), start datetime, [end] datetime)
insert into @temp values('e1', '1/1/2009', '2/1/2009')
insert into @temp values('e2', '1/15/2009', '1/31/2009')
insert into @temp values('e3', '8/15/2008', '1/16/2009')
insert into @temp values('e4', '2/3/2009', '2/15/2009');
select * from @temp where start < '2/1/2009' and [end] >= '2/1/2009'
select * from @temp where start < '2/2/2009' and [end] >= '2/2/2009'
C#/ linq:
public class Event
{
public string eventID;
public DateTime start;
public DateTime end;
}
static void Main(string[] args)
{
IList<Event> events = new List<Event>();
events.Add(new Event { eventID = "e1", start = new DateTime(2009, 1, 1), end = new DateTime(2009, 2, 1) });
events.Add(new Event { eventID = "e2", start = new DateTime(2009, 1, 15), end = new DateTime(2009, 1, 31) });
events.Add(new Event { eventID = "e3", start = new DateTime(2008, 8, 15), end = new DateTime(2009, 1, 16) });
events.Add(new Event { eventID = "e4", start = new DateTime(2009, 2, 3), end = new DateTime(2009, 2, 15) });
DateTime eventDate = new DateTime(2009, 2, 1);
var available = events.Where(e => e.start.CompareTo(eventDate) < 1 && e.end.CompareTo(eventDate) > -1);
Console.WriteLine(available.Count());
eventDate = new DateTime(2009, 2, 2);
available = events.Where(e => e.start.CompareTo(eventDate) < 1 && e.end.CompareTo(eventDate) > -1);
Console.WriteLine(available.Count());
eventDate = new DateTime(2009, 1, 16);
available = events.Where(e => e.start.CompareTo(eventDate) < 1 && e.end.CompareTo(eventDate) > -1);
Console.WriteLine(available.Count());
Console.ReadLine();
}
编辑:这不太好,但是这个SQL会给你你要求的结果:
declare @temp table (evt varchar(10), start datetime, [end] datetime)
declare @result table (available datetime)
insert into @temp values('e1', '1/1/2009', '2/1/2009')
insert into @temp values('e2', '1/15/2009', '1/31/2009')
insert into @temp values('e3', '8/15/2008', '1/16/2009')
insert into @temp values('e4', '2/3/2009', '2/15/2009');
declare @start datetime
declare @end datetime
set @start = '1/1/2009'
set @end = '2/16/2009'
while @start < dateadd(day, 1, @end)
begin
declare @rowCount int
select @rowCount = count(*) from @temp where start <= @start and [end] >= @start
if @rowCount = 0
insert into @result values(@start)
set @start = dateadd(day, 1, @start)
end
select * from @result
答案 2 :(得分:0)
如果您使用日期或日历类型表,则此类查询很容易。这些是使用的实用程序表,因此您有一个预先填充的表,其中的字段在查询中进行计算会很繁琐(例如,IsWeekDay,IsHoliday,FiscalMonth)。下面我使用了一个非常简单的日历表。获取没有事件的日期的查询最终非常简单。
这是在SQL Server 2005上创建的
-- Create the #Calendar table
Create table #Calendar (CalendarDate datetime)
Set nocount on
Declare @Date smalldatetime
Set @Date = '1/1/2000'
While @Date < '1/1/2015'
Begin
Insert #Calendar select @Date
Set @Date = dateadd(dd, 1, @Date)
End
-- Create the #Event table
Create Table #Event (EventName varchar(10), StartDate datetime, EndDate datetime)
Insert Into #Event
Select 'e1', '1/1/2009', '2/1/2009'
Union Select 'e2', '1/15/2009', '1/31/2009'
Union Select 'e3', '8/15/2008', '1/16/2009'
Union Select 'e4', '2/3/2009', '2/15/2009'
-- Return all the dates that do not have events
Select #Calendar.CalendarDate
From #Calendar
Left Join #Event
on #Calendar.CalendarDate between #Event.StartDate and #Event.EndDate
Where
#Event.StartDate is null
and CalendarDate between
(Select min(StartDate) from #Event)
and
(Select max(EndDate) from #Event)