перекрывающиеся встречи с использованием структуры объекта - PullRequest
2 голосов
/ 03 марта 2010

Я использую asp.net mvc с Entity Framework. У меня есть список встреч с полем startat, полем endat и полем roomid (называемый SpaceConfigurationId), и я хотел бы найти список встреч, которые были забронированы дважды для данной комнаты. Можно предположить, что окончание всегда идет после запуска.

Существует 4 случая, когда можно было бы назначить встречу:

  1. встреча a начинается до того, как встреча b начинается и заканчивается после начала встречи b и до того, как встреча b заканчивается
  2. встреча a начинается после начала встречи b и до того, как встреча b заканчивается и заканчивается после того, как встреча b заканчивается
  3. встреча a начинается до встречи b начинается и заканчивается после окончания встречи b
  4. назначение a начинается после начала назначения b и до окончания назначения b и заканчивается после начала назначения b и до окончания назначения b

Я бы хотел список назначений, которые соответствуют любому из этих требований. Это кажется простым, но на самом деле это игра ума. Я посмотрел на пересечение, но, похоже, никуда не деться. Я определил следующую переменную и хотел бы вернуть список.

IQueryable<Appointment> appointments = Repository.ReadAppointments();
... insert code here ...
return appointments.ToList();

Вот некоторый SQL, который очень медленный, но может помочь обрисовать проблему

select COUNT(*)
from appointment a
    cross join appointment b
where
    not a.Id = b.Id
    AND
    a.SpaceConfigurationId = b.SpaceConfigurationId
    AND
    (
        (a.StartedAt < b.StartedAt and a.EndedAt > b.StartedAt and a.EndedAt < b.EndedAt)
        OR 
        (a.StartedAt > b.StartedAt and a.StartedAt < b.EndedAt and a.EndedAt > b.EndedAt)
        OR 
        (a.StartedAt < b.StartedAt and a.EndedAt > b.EndedAt)
        OR 
        (a.StartedAt > b.StartedAt and a.StartedAt < b.EndedAt and a.EndedAt > b.StartedAt and a.EndedAt < b.EndedAt)
    )

1 Ответ

1 голос
/ 03 марта 2010
  1. Определение индексов для SpaceConfigurationId и столбцов даты.
  2. Есть 2 случая, когда встречи не совпадают:

    1. Когда заканчивается до b.
    2. Когда a начинается после b.

Так ..

select COUNT(*)
from appointment a
join appointment b
on
    (not a.Id = b.Id)
    AND
    (a.SpaceConfigurationId = b.SpaceConfigurationId)
    AND
    NOT (a.EndetAt < b.StartedAt)
    AND
    NOT (a.StartedAt > b.EndetAt)

Итак ...

repository.ReadAppointments().Where(a => repository.ReadAppointments().
     Any(b => 
         !(b.ID == a.ID) && 
         (a.SpaceConfigurationId == b.SpaceConfigurationId) &&
         !(a.EndetAt < b.StartedAt) &&
         !(a.StartedAt > b.EndetAt))).
     Select(t => t.ID).ToList();

Он не генерирует тот же SQL. На самом деле он использует EXISTS, но с правильными индексами должно работать нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...