【问题标题】:Entity Framework - GroupBy then OrderBy实体框架 - GroupBy 然后 OrderBy
【发布时间】:2018-04-01 05:19:02
【问题描述】:

我有一组记录,其中包括 PatientID 和 Appointment Date。

我想按 PatientID 对它们进行分组,并按每个 PatientID 组中最早的约会对这些组进行排序。像这样……

 ID     ApptDate
----------------------
  3    2/5/2005   (oldest compared to all groups , so group "ID = 3" is sorted first)
  3    5/10/2006
  3    6/2/2010

  1    8/5/2007
  1    9/1/2015 

  2    6/15/2009
  2    9/19/2009        

我很确定我需要先使用分组来获取每个 ID 的最旧日期值,然后按该值排序,但我无法理解这两个函数如何协同工作。

var query = from a in db.Appointments
group a by new { a.Id, a.ApptDate} into pa
select new { 
     ID = pa.Key.Id,  
     Date = pa.Min(x =>x.ApptDate) ...

...但我此时崩溃并燃烧。

任何帮助表示赞赏。

【问题讨论】:

  • 尝试先下单再分组
  • 来自 GroupBy 的文档 IGrouping 对象的生成顺序基于源中生成每个 IGrouping。分组中的元素按照它们在源代码中出现的顺序产生。
  • 为什么还要按 ApptDate 分组?为什么不简单地按 Id 分组,然后按 value.Select(x=>x.Min(y=>y.ApptDate)) 对组进行排序?
  • 应该是 Min() 调用,因为您的问题是先对最旧的记录进行排序。
  • Tanveer - 你是对的。我更改了我的示例代码。

标签: c# entity-framework group-by sql-order-by


【解决方案1】:

我修改了一点 Tanveer Badar 的答案,为每个实体返回一行。

为您的返回数据创建一个类

public class ReturnType
{
    public int ID { get; set; }
    public DateTime AppDate { get; set; }
}

获取一组 ID 和可枚举的有序日期

var result = db.Appointment
            .GroupBy(a => a.Id)
            .OrderBy(a => a.Min(n => n.Date))
            .Select(a => new { ID = a.Key, AppDates = a.OrderBy(na => 
na.Date).Select(ne => ne.Date) })
            .ToList();

然后展平返回的列表。我尝试了 SelectMany 但没有成功。

var results = new List<ReturnType>();
        foreach (var a in result)
        {
            foreach (var date in a.AppDates)
            {
                var returnType = new ReturnType
                {
                    ID = a.ID,
                    AppDate = date
                };

                results.Add(returnType);
            }
        }

【讨论】:

  • 返回一个按 PatientID 排序的列表
  • @RPollack 你确定吗?我使用您提供的示例对其进行了完全测试,它返回了正确的值。
  • 对,不使用核心。让我再试一次
  • @RPollack 我认为因为在 EF Core(2.1 之前)中,GroupBy 转换为 OrderBy,然后它将返回按 PatientID 排序的值。但是由于您使用EF。 GroupBy 工作正常,如果你检查代码,没有 PatientID 排序,所以你得到的东西对我来说看起来很奇怪。
  • 是的。您修改后的答案有效!我只需要在“var returnType = new ReturnType”行的末尾添加“()”。谢谢!
【解决方案2】:

您的要求如下(虽然问题没有提到其中之一,但从数据的布局方式可以看出):

  1. 基于患者 ID 的组。
  2. 根据每个组中最早的约会日期对组进行排序。
  3. 根据约会日期对组内的数据进行排序。

var query = records.GroupBy(r => r.PatientId) // Group patients .OrderBy(g => g.Min(r => r.AppointmentDate)) // sort groups by oldest record in each .Select(g => new { PatientId = g.Key, Records = g.OrderBy(r => r.AppointmentDate) // sort records within a group by oldest });

【讨论】:

  • 是的,关于要求 3,您是正确的,但是您的代码似乎只返回每位患者(组)的一行,而不是每位患者的所有行。
  • 您需要运行嵌套循环来遍历所有数据。您是否尝试过在调试器中可视化查询结果?
【解决方案3】:

在我的情况下它工作正常......

var query = from a in db.Appointments
    group a by new { a.Id, a.ApptDate} into pa
    select new { 
         ID = pa.Key.Id,  
         Date = pa.Max(x =>x.ApptDate)
       }).Select(x=>new { 
                             x.ID,x.Date
                            }).ToList();

【讨论】:

  • 应该是 pa.Min() 因为最旧的记录首先出现,其次您的答案中没有 OrderBy()。
  • 这将返回一个按患者 ID 排序的列表,而不是按每个患者 ID 组中最早的预约日期排序。
  • 按照建议,我在 .Select 之前添加了 OrderBy(y => y.Date) 并且它确实正确排序,但每个 PatientID 只返回一行。如何让其他 PatientID 行显示?
【解决方案4】:
db.Appointments.GroupBy(new {ID = item.ID, ApptDate = item.ApptDate}).OrderByDescending(item => item.ApptDate)

【讨论】:

  • 这甚至不会编译,因为 IGrouping 没有属性“ApptDate”。
猜你喜欢
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多