2013-10-04 4 views
3

у меня есть таблица, которая выглядит, как это отслеживание, когда человек начал проект:Linq запрос, чтобы найти диапазон дат

PersonId 
ProjectId 
StartDate 

Я хочу использовать LINQ (LINQ к лицам), чтобы получить результат установить как этот

PersonId 
ProjectId 
StartDate 
EndDate 

Где EndDate является StartDate их следующего проекта (если не заказан StartDate) или нулевое значение, если нет более недавний проект.

Это то, что я сделал:

context.PersonProjects.Select(pp => new { 
    pp.PersonId, 
    pp.ProjectId, 
    pp.StartDate, 
    EndDate = context.PersonProjects.Where(pp2 => pp2.PersonId == pp.PersonId && pp2.StartDate > pp.StartDate).OrderBy(pp2 => pp2.StartDate).Select(pp2 => pp2.StartDate).FirstOrDefault() 
}) 

Есть ли более производительный способ сделать это?

ответ

1

Более совершенный (но не такой чистый) способ сделать это будет читать все в список, упорядоченный в дату начала, а затем ходить по списку и захватывать дату начала следующего элемента, если таковой имеется :

// You need a named class in order to make this work 
class PersonProject { 
    int PersonId {get;set;} 
    int ProjectId {get;set;} 
    DateTime StartDate {get;set;} 
    DateTime EndDate {get;set;} 
} 
... 
// Run your query, and put the results in a list 
var listOfProjects = context 
    .PersonProjects 
    .OrderBy(pp => pp.StartDate) 
    .Select(pp => new PersonProject { 
     PersonId = pp.PersonId, 
     ProjectId = pp.ProjectId, 
     StartDate = pp.StartDate 
    }).ToList(); 
// Now walk through the list, setting the end time to the start of the next item 
for (int i = 0 ; i < listOfProjects.Length-1 ; i++) { 
    listOfProjects[i].EndDate = listOfProjects[i+1].StartDate; 
} 

запроса и «исправить» части для этого решения является линейным, так что производительность будет столь же хорошо, как чтение самого PersonProject таблицы.

+0

Спасибо, это имеет смысл. Эта конкретная таблица имеет около 300K строк, поэтому я не уверен, что загружаю их все в память. Часто я просто хочу получить совокупность этих результатов (например, найти количество людей, которые работали над проектом в течение определенного периода времени), что означает, что это всего лишь базовый запрос для другого запроса, поэтому кажется идеальным для его сохранения. IQuerya ble – Adam

+0

@Adam Если вы установите «фиксированный цикл» в отдельный метод, который берет правильно упорядоченный список, вы сможете сохранить «IQueryable» и выполнять исправление только тогда, когда нужное подмножество находится в памяти. – dasblinkenlight

+0

Правда, я просто не могу использовать «EndDate» для фильтрации результатов до тех пор, пока цикл исправления не будет установлен. Иногда я захочу. Мне, возможно, придется сделать некоторые тесты и посмотреть, как это сравнивается. – Adam

Смежные вопросы