linq,用于获取每个不同名称的5条最新记录

kiayqfof  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(364)

我一直在尝试从数据库中获取5条最新的记录,这些记录的名称与“name”列中的不同。这意味着我需要表中每个唯一名称的5条最新记录。
下面是一个示例表:

id  |   Name   |  Status  | Start      | End     <br />
1   |  Bob     |  Pass    | 2020-01-01 | 2020-01-01<br />
2   |  Chris   |  Pass    | 2020-01-01 | 2020-01-02<br />
3   |  James   |  Fail    | 2020-01-01 | 2020-01-03<br />
4   |  Bob     |  Pass    | 2020-01-01 | 2020-01-04<br />
5   |  Chris   |  Fail    | 2020-01-01 | 2020-01-05<br />
6   |  Bob     |  Pass    | 2020-01-01 | 2020-01-06<br />
7   |  Bob     |  Fail    | 2020-01-01 | 2020-01-07<br />
8   |  Bob     |  Fail    | 2020-01-01 | 2020-01-08<br />
9   |  Chris   |  Pass    | 2020-01-01 | 2020-01-09<br />
10  |  Bob     |  Pass    | 2020-01-01 | 2020-01-10<br />

我希望最新的5鲍勃记录(6),3克里斯记录,和一詹姆斯记录将返回。
到目前为止,我已经尝试了以下方法:
把它分成两部分perations:querying for 不同的名称,然后根据名称进行查询,按enddate获取最新的5条记录并附加到列表中。使用此方法,我能够正确地执行第一个查询。我正在打印三个不同的名字(鲍勃、克里斯、詹姆斯)。然而,每次我用这些名字做一个查询,得到5个最新的记录,这三个名字的结果都是空的。根据VisualStudio2019,我尝试进行的任何打印都表明变量名无效…所以我尝试了方法2

// GET: api/Student/latestRecords
[HttpGet("latestRecords")]
public async Task<ActionResult<IEnumerable<Student>>> GetLatestRecordsOnAllStudent()
{
    var distinctStudentNames = _context.Students.Select(x => x.name).Distinct();

    IQueryable<Student> allRecords = new Student[] { }.AsQueryable();

    foreach (string studentName in distinctStudentNames)
    {
        var newList = _context.Students.OrderByDescending(x => x.endTime).DistinctBy(y => y.name).Select( z => z).Take(5);

        allRecords.Concat(newList);
    }

    return allRecords.ToList();*/
}

使用单个linq查询。使用这个方法,我可以根据名称得到3个不同的记录,但我不能得到更多的记录。

// GET: api/Student/latestRecords
[HttpGet("latestRecords")]
public async Task<ActionResult<IEnumerable<Student>>> GetLatestRecordsOnAllStudents()
{
    var distinctStudentsNames = _context.Students.DistinctBy(x => x.name).OrderByDescending(x => x.endTime).Select(z => z).Take(5).ToList();

    return distinctStudentsNames;
}

如果方法2能起作用,我会很高兴的,但我觉得我可能会在一次调用中尝试完成这一切。如果有人有什么建议,我们将不胜感激。

bzzcjhmw

bzzcjhmw1#

由于您使用的是ef-core,因此您只能使用ef-core进行操作 GroupBy . 相反,你可以替换 GroupBy 一个子查询,返回每个 name :

var allRecords = from s in _context.Students
                 where (from s2 in _context.Students
                        where s2.name == s.name
                        orderby s2.endTime descending
                        select s2.id).Take(5).Contains(s.id)
                 orderby s.name, s.endTime descending
                 select s;

或者,如果你喜欢流利的版本:

var allRecords2 = _context.Students.Where(s => _context.Students.Where(s2 => s2.name == s.name)
                                                       .OrderByDescending(s2 => s2.endTime)
                                                       .Select(s2 => s2.id)
                                                       .Take(5)
                                                       .Contains(s.id))
                                    .OrderBy(s => s.name)
                                    .ThenByDescending(s => s.endTime);
r8uurelv

r8uurelv2#

编辑:

正如@netmerge指出的那样,这在ef core中是行不通的,所以我现在就把答案留在这里,以防op想看看它。
下面是一个示例类,它只包含我们关注的两个属性,以及您的示例列表。

public class Student
{
    public string Name { get; set; }
    public DateTime End { get; set; }
}

var students = new List<Student>
{
    new Student() { Name = "Bob", End = new DateTime(2020, 1, 1) },
    new Student() { Name = "Chris", End = new DateTime(2020, 1, 2) },
    new Student() { Name = "James", End = new DateTime(2020, 1, 3) },
    new Student() { Name = "Bob", End = new DateTime(2020, 1, 4) },
    new Student() { Name = "Chris", End = new DateTime(2020, 1, 5) },
    new Student() { Name = "Bob", End = new DateTime(2020, 1, 6) },
    new Student() { Name = "Bob", End = new DateTime(2020, 1, 7) },
    new Student() { Name = "Bob", End = new DateTime(2020, 1, 8) },
    new Student() { Name = "Chris", End = new DateTime(2020, 1, 9) },
    new Student() { Name = "Bob", End = new DateTime(2020, 1, 10) }
};

你可以做一个 GroupBy() 然后 OrderByDescending() 这个 End 属性,每个属性取5个。

var recentFiveForEachName = students
            .GroupBy(x => x.Name, (key, g) => g.OrderByDescending(y => y.End).Take(5));

相关问题