LINQ to SQL - упорядочить по, упорядочить по и упорядочить по каждой группе с помощью skip and take - PullRequest
0 голосов
/ 31 мая 2018

Это расширение уже отвеченного вопроса Джона Скита, которое вы можете найти здесь.

Желаемый результат следующий:

A 100
A 80
B 80
B 50
B 40
C 70
C 30

, учитывая, что у вас естьследующий класс:

public class Student
{
    public string Name { get; set; } 
    public int Grade { get; set; }
}

, чтобы получить результат (в идеальном сценарии), можно сделать с помощью ответа Джона Скита:

var query = grades.GroupBy(student => student.Name)
                  .Select(group => 
                        new { Name = group.Key,
                              Students = group.OrderByDescending(x => x.Grade) })
                  .OrderBy(group => group.Students.FirstOrDefault().Grade);

Однако в моем случае я должен поддерживать подкачку в моемзапрос также.Это означает выполнение SelectMany () , а затем выполнение Skip () и Take () .Но чтобы сделать Skip () , вам нужно применить OrderBy () .Вот где мой заказ снова ломается, так как мне нужно сохранить заказ, который я получаю после SelectMany () .

Как этого добиться?

var query = grades.GroupBy(student => student.Name)
                  .Select(group => 
                        new { Name = group.Key,
                              Students = group.OrderByDescending(x => x.Grade) })
                  .OrderBy(group => group.Students.FirstOrDefault().Grade).SelectMany(s => s.Students).OrderBy(something magical that doesn't break ordering).Skip(s => skip).Take(t => take);

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

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Вы можете использовать другой подход, используя Max вместо упорядочения каждой группы и получения первого значения.После этого вы можете заказать по максимальной оценке, имени (в случае, если у двух учащихся одинаковая максимальная оценка) и оценке:

var query = c.Customers
    .GroupBy(s => s.Name, (k, g) => g
        .Select(s => new { MaxGrade = g.Max(s2 => s2.Grade), Student = s }))
    .SelectMany(s => s)
    .OrderBy(s => s.MaxGrade)
    .ThenBy(s => s.Student.Name)
    .ThenByDescending(s => s.Student.Grade)
    .Select(s => s.Student)
    .Skip(toSkip)
    .Take(toTake)
    .ToList();

Все эти методы поддерживаются EF6, поэтому вы должны получить желаемый результат.

0 голосов
/ 31 мая 2018

Просто переиндексируйте результаты списка и удалите индекс перед возвратом.

var query = grades.GroupBy(student => student.Name)
       .Select(group => 
               new { Name = group.Key, 
                    Students = group.OrderByDescending(x => x.Grade)
                   })
       .OrderBy(group => group.Students.FirstOrDefault().Grade)
       .SelectMany(s => s.Students)
       .Select((obj,index) => new {obj,index})
       .OrderBy(newindex => newindex.index)
       .Skip(s => skip).Take(t => take)
       .Select(final=> final.obj);
...