Обновлено: объединение всех удалено
declare @tbl table (
idx int identity(1,1) primary key,
startdate datetime,
enddate datetime);
insert into @tbl (startdate, enddate)
select '2009-01-01', '2009-01-05'
union all select '2009-01-02', '2009-01-04'
union all select '2009-01-01', '2009-01-03'
union all select '2009-01-03', '2009-01-06'
union all select '2009-01-04', '2009-01-07'
union all select '2009-01-05', '2009-01-08'
select idx, startdate
, (select sum(in_or_out)
from (
select case when startdate<=all_events.startdate then 1 else 0 end
+ case when enddate <= all_events.startdate then -1 else 0 end as in_or_out
from @tbl
where startdate <= all_events.startdate
or enddate <= all_events.startdate) as previous
) as concurent
from @tbl all_events
order by startdate
Это дает временную шкалу начала сеанса с количеством одновременных сеансов в момент запуска нового сеанса:
idx startdate concurent
3 2009-01-01 00:00:00.000 2
1 2009-01-01 00:00:00.000 2
2 2009-01-02 00:00:00.000 3
4 2009-01-03 00:00:00.000 3
5 2009-01-04 00:00:00.000 3
6 2009-01-05 00:00:00.000 3
Чтобы получить исходный запрос (набор параллельных сеансов с максимальным параллелизмом), вам нужно запустить этот запрос дважды, один раз, чтобы получить максимальное количество одновременных сеансов, и один раз, чтобы получить даты начала сеансов, которые имеют максимальное количество одновременных сеансов, затем вы должны получить эти сессии.
Обновлено
Итак, вот один единственный запрос, который извлекает максимальное количество одновременных сеансов. Я изменил тестовые данные, чтобы удалить неоднозначные перекрытия конца и начала:
declare @tbl table (
idx int identity(1,1) primary key,
startdate datetime,
enddate datetime);
insert into @tbl (startdate, enddate)
select '2009-01-01', '2009-01-04 23:59:59'
union all select '2009-01-02', '2009-01-03 23:59:59'
union all select '2009-01-01', '2009-01-02 23:59:59'
union all select '2009-01-03', '2009-01-03 23:59:59'
union all select '2009-01-04', '2009-01-04 23:59:59'
union all select '2009-01-05', '2009-01-05 23:59:59'
select max_concurent_starts.startdate as concurentdate
, session.*
from (
select *
,(
select sum(in_or_out)
from (
select case when startdate<=all_events.startdate then 1 else 0 end
+ case when enddate <= all_events.startdate then -1 else 0 end
as in_or_out
from @tbl
where startdate <= all_events.startdate
or enddate <= all_events.startdate) as previous
) as concurent
from @tbl all_events) as max_concurent_starts
join @tbl as session
on session.startdate <= max_concurent_starts.startdate
and session.enddate >= max_concurent_starts.startdate
where concurent = (
select top 1 concurent
from (
select (
select sum(in_or_out)
from (
select case when startdate<=all_events.startdate then 1 else 0 end
+ case when enddate <= all_events.startdate then -1 else 0 end
as in_or_out
from @tbl
where startdate <= all_events.startdate
or enddate <= all_events.startdate) as previous
) as concurent
from @tbl all_events) as all_events_with_concurent
order by concurent desc)
order by concurentdate, startdate;
Это дает такой результат, как:
concurentdate idx startdate enddate
2009-01-02 00:00:00.000 3 2009-01-01 00:00:00.000 2009-01-02 23:59:59.000
2009-01-02 00:00:00.000 1 2009-01-01 00:00:00.000 2009-01-04 23:59:59.000
2009-01-02 00:00:00.000 2 2009-01-02 00:00:00.000 2009-01-03 23:59:59.000
2009-01-03 00:00:00.000 1 2009-01-01 00:00:00.000 2009-01-04 23:59:59.000
2009-01-03 00:00:00.000 2 2009-01-02 00:00:00.000 2009-01-03 23:59:59.000
2009-01-03 00:00:00.000 4 2009-01-03 00:00:00.000 2009-01-03 23:59:59.000
который гласит: 2009-01-02 00:00:00
было 3 одновременных сеанса (3, 1 и 2) с соответствующими началами и окончаниями. Ничья, 2009-01-03 00:00:00
было также 3 одновременных сеанса (1, 2 и 4) с их соответствующими началами и окончаниями.
Пробег производительности может варьироваться. Запрос может быть написан в 1 миллион раз проще в SQL 2005 с использованием CTE.
person
Remus Rusanu
schedule
18.09.2009