【问题标题】:Linq Group by and Order byLinq Group by 和 Order by
【发布时间】:2017-02-06 14:58:30
【问题描述】:

我有一个 sql 查询,我按Name 分组,然后按Date 排序。 我还需要为每个组选择一个最新日期的条目。 我如何在 linq 中做到这一点(使用 lambda 表达式)?

select Name,Date,Comment 
from Feedback
Group by Name,Date,Comment
order by Date desc

我的 linq

var query= db.Feedback
                .GroupBy(f => f.Name, (f, g) => new
                {
                    Name = f,
                    Comment = g.Select(h => h.Comment),
                    Date= g.Select(h => h.Date)
                })
                .Select(f => new { f.Name, f.Date, f.Comment}).ToList();

如何按Date desc 对每个组进行排序并取第一个条目?

编辑

我已将查询更新为

    var query= db.Feedback.GroupBy(f => new { f.Name, f.Comment })
                .Select(a => a.AsEnumerable())
                .Select(b => b.OrderByDescending(f => f.Date)
                .Select(c=>new{c.Name,c.Date,c.Comment}));

...执行最后一个 Select 可防止 JsonSerializer 中出现引用循环错误。

我的数据应该是这样的

姓名:姓名1 日期:9月28日 评论:评论文字

名称:名称2 日期:8 月 15 日 评论:评论文字

...但看起来是这样的:

姓名:姓名1 日期:9月28日 评论:评论文字

名称:名称2 日期:8 月 15 日 评论:评论文字

姓名:姓名1 日期:8 月 1 日 评论:评论文字

...这是解决方案

        var query= db.Feedback
                .GroupBy(f => new { f.Name})
                .Select(a => a.AsEnumerable())
                .Select(b => b.OrderByDescending(f => f.Date)
                    .Select(c => new { c.Name, c.Date, c.Comment})
                    .FirstOrDefault());

【问题讨论】:

  • 你想要每个组的第一个元素吗?
  • 是的,按最新日期。

标签: c# sql linq linq-to-entities


【解决方案1】:

您的查询将是:

var query= from f in db.Feedback
           group f by new {f.Name, f.Date, f.Comment} into g
           orderby g.Key.Date descending
           select new {g.Key.Name, g.Key.Date, g.Key.Comment};

还有:

var query= from f in db.Feedback
           group f by new {f.Name, f.Date, f.Comment} into g
           orderby g.Key.Date descending
           select g.Key;

如果你想要第一个元素,请使用FirstOrDefault 扩展方法:

var first= query.FirstOrDefault();

如果您希望每个组的第一个元素按Date 排序,那么您也可以这样做:

var query= from f in db.Feedback
           group f by new {f.Name, f.Date, f.Comment} into g
           select g.OrderByDescending(e=>e.Date).FirstOrDefault();

如果您只想按名称进行分组,请执行以下操作:

var query= from f in db.Feedback
           group f by f.Name into g
           select g.OrderByDescending(e=>e.Date).FirstOrDefault();

【讨论】:

  • 我想获取按名称分组的最新日期/评论项目。 FirstOrDefault() 会给我整个查询的第一项。
  • @agri,现在查看我的答案
  • ..由于实际数据库引用了其他表,我得到“检测到自引用循环”。如何打破循环?
  • 有几种方法可以做到这一点,here 你会很多。一种简单的方法是在您的上下文中禁用延迟加载和代理创建
【解决方案2】:

您不能在日期列上应用GroupBy,然后再应用OrderBy。因为如果你在GroupBy 中有它,它只会在每个组中为你提供一个 Date 值。因此,如果您想按日期订购,则应将其从 group by 中删除并使用:

var q = db.Feedback
            .GroupBy(f => new {f.Name, f.Comment})
            .Select( a => a.AsEnumerable())
            .Select(b=> b.OrderByDescending(f => f.Date))
        ;

foreach (var item in q)
{
    Debug.Log(item.FirstOrDefault().ToString());
}

【讨论】:

  • 由于 Date 是数据库中的 datetime 类型,因此它给了我“DbSortClause 表达式必须具有可与订单比较的类型”错误
猜你喜欢
  • 2011-06-28
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多