首页 > 解决方案 > LINQ 用于获取每个不同名称的 5 条最新记录

问题描述

我一直在尝试从“名称”列中具有不同名称的数据库中获取 5 条最新记录。这意味着我想要表中每个唯一名称的 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 条 Bob 记录(共 6 条)、3 条 Chris 记录和 1 条 James 记录。

到目前为止,我已经尝试过以下方法:

  1. 将其分为两个不同的操作:查询 Distinct 名称,然后根据名称查询,通过 endDate 获取最新的 5 条记录并附加到列表中。使用这种方法,我能够正确执行第一个查询。我打印出三个不同的名字(Bob、Chris、James)。但是,每次我使用这些名称进行查询并获取 5 条最新记录时,所有三个名称都会返回为空。根据 Visual Studio 2019,我尝试进行的任何打印都表示变量名无效......所以我尝试了方法 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();*/
}
  1. 使用单个 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 可行,我会喜欢它,但我觉得我可能会踩到自己的脚趾,试图在一个电话中完成所有操作。如果有人有一些建议,将不胜感激。

标签: c#sqllinqentity-framework-core

解决方案


编辑:

正如@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()然后属性,然后从每个中取 5 个OrderByDescending()End

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

推荐阅读