2014-09-08 2 views
1

Как использовать LINQ to Entities для выполнения следующего запроса.LINQ версия Where In Subquery With Max и Group

SELECT [id] ,[value1], [value2], [dateValue] 
FROM table 
WHERE dateValue IN (
    SELECT MAX(dateValue) 
    FROM table 
    GROUP BY id 
) 

Есть несколько записей в таблице с тем же идентификатором, так что я просто хочу один из каждого идентификатора с наибольшим значением даты. Кроме того, dateValue включает компонент времени до миллисекунд и не будет дублироваться.

Я знаю, что LINQ To Entities не поддерживает ключевое слово IN, но я читал, что вы все еще можете работать с подзапросами с помощью метода context.tableName.Any() или путем добавления запроса внутри части Select.

Using context = ContextProvider.GetContext() 
    Dim table = context.tableName 

    Dim query = _ 
     From rows In table _ 
     Select New ClassName With _ 
       { _ 
        .Id = rows.Id, _ 
        .Value1 = rows.Value1, _ 
        .Value2 = rows.Value2, _ 
        .DateValue = rows.DateValue _ 
       } 

    Return query.ToList() 
End Using 

Учитывая вышесказанное, я не уверен, что должно быть в запросе на Where table.Any(..., или .DateValue = subquery в Select, чтобы получить то, что я хочу. И в любой ситуации я не уверен, как отформатировать выражение.

+0

Почему вы группируете по id в подзапросе, если вы просто хотите MAX (dateValue)? Вы хотите, чтобы первая запись за один ID с MAX (dateValue)? Тогда запрос sql неверен. –

+0

Да, есть несколько записей с одним и тем же идентификатором, и я просто хочу 1 запись на идентификатор с наибольшей датой для этого идентификатора. –

+0

Каков первичный ключ вашей таблицы? –

ответ

1

На самом деле ваш sql уже неверен, потому что нет никакой связи между подзапросом и основным запросом, кроме даты. Если у вас есть идентификатор с dateValue, который является максимальным значением даты другого идентификатора, вы получаете эту запись с неправильным идентификатором.

Так что, если вы хотите, чтобы запись с наибольшей Датой на ID я хотел бы сделать:

WITH CTE AS 
(
    SELECT rn = ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY [dateValue] DESC), 
      [id] ,[value1], [value2], [dateValue] 
    FROM table 
) 
SELECT [id] ,[value1], [value2], [dateValue] 
FROM CTE 
WHERE RN = 1 

В LINQ это должно работать (я не знаком с Linq-To-Entities):

Dim query = From row In table 
      Group row By row.Id into idGrp 
      Let MaxDatePerID = idGrp.Max(Function(r) r.DateValue) 
      From idRow In idGrp 
      Where idRow.DateValue = MaxDatePerID 
      Select New ClassName With 
      { 
       .Id = idRow.Id, 
       .Value1 = idRow.Value1, 
       .Value2 = idRow.Value2, 
       .DateValue = idRow.DateValue 
      } 
+0

Я запустил обычный SQL-запрос к таблице и вернул мне правильные результаты. Я даже дважды проверял даты отдельно, используя таблицу SELECT MAX (dateValue) FROM, где id = ... 'для каждого идентификатора в таблице, а даты совпадают. Я не говорю, что ваш метод неверен, я дам ему попробовать, но мой SQL-запрос не кажется неправильным, как вы предлагаете. –

+1

@JeremyK: рассмотрите эти три строки: 1) 'ID = 1, DateValue = 2014/9/7' 2)' ID = 1, DateValue = 2014/9/8' 3) 'ID = 2, DateValue = 2014/9/7'. Теперь вы получаете также первую запись, даже если это не максимальная дата для этого идентификатора, поскольку эта дата является датой, которая является максимальной датой другого идентификатора. –

+0

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

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

  • Нет связанных вопросов^_^