2014-11-13 7 views
2

У меня есть класс модели в C#, привязанный к базе данных с сущностью. В моей модели я записываю значения для пользователей и время записи записи. Я хочу вернуть набор записей, которые представляют собой только самую последнюю запись для данного UserID.Self join with aggregate query в LINQ

Я могу выполнить это в SQL с агрегированным запросом (максимальная дата, сгруппированная по ID пользователя) и самосоединением, чтобы соответствовать этим параметрам с правильной записью.

DECLARE @UserValues 
    TABLE 
    (
     id INT IDENTITY(1,1) PRIMARY KEY, 
     UserID INT, 
     Value CHAR, 
     RecordedAt DATETIME 
    ) 

INSERT INTO @UserValues (UserID, Value, RecordedAt) SELECT 3, 'a', '2014-11-06'; 
INSERT INTO @UserValues (UserID, Value, RecordedAt) SELECT 3, 'b', '2014-11-08'; 
INSERT INTO @UserValues (UserID, Value, RecordedAt) SELECT 3, 'c', '2014-11-04'; 
INSERT INTO @UserValues (UserID, Value, RecordedAt) SELECT 5, 'f', '2014-11-03'; 
INSERT INTO @UserValues (UserID, Value, RecordedAt) SELECT 5, 'h', '2014-11-23'; 
INSERT INTO @UserValues (UserID, Value, RecordedAt) SELECT 5, 'w', '2014-11-07'; 

select straight_data.* 
from 
(
    select UserID   as UserID, 
      MAX(RecordedAt) as RecordedAt 
     from @UserValues 
    group by UserID 
) as max_date 
join @UserValues as straight_data 
    on max_date.RecordedAt = straight_data.RecordedAt 
and max_date.UserID  = straight_data.UserID 

В результате только самая последняя запись для каждого пользователя:

id UserID Value RecordedAt 
5 5  h  2014-11-23 00:00:00.000 
2 3  b  2014-11-08 00:00:00.000 

в действии здесь: http://sqlfiddle.com/#!6/7c4dc/1

Таким образом, вопрос, как я выполняю ниже операции в LINQ на что-то вроде,

ICollection<UserValues> MyUserValues; 

ответ

3

Вы можете сделать это в linq с помощью этих шагов s:

Группа по USERID

Заказать каждую группу по RecordedAt (по убыванию)

Выберите первый из каждой "группы".

var dataByUserAndMaxDate = 
    MyUserValues.GroupBy(m => m.UserId) 
       .Select(m => m.OrderByDescending(x => x.RecordedAt).First()); 

Там также метод MaxBy расширения, если вы используете MoreLinq (для LINQ только объекты)

+0

Brilliant, я проверил его здесь: https://dotnetfiddle.net/BUwR3L – darkpbj