【问题标题】:Order by user and then select max date按用户订购,然后选择最大日期
【发布时间】:2016-10-13 22:24:01
【问题描述】:

我有这个 LINQ 查询:

ArrayList arr = new ArrayList();
var data = conn.SCOT_DADOS.OrderByDescending(x => x.DATE)
                          .GroupBy(r => r.USER)
                          .ToList();
foreach (var item in data)
{
    var itemdata = item.Where(r => r.DATE == item.Max(s => s.DATE));

    var name = svc.GetUserName(itemdata.Select(r => r.USER).First().ToString());
    var value = itemdata.Select(r => r.VALUE).First();
    var date = itemdata.Select(r => r.DATE).First().ToString("dd/MM/yyyy HH:mm:ss");

    arr.Add( new{ NAME = name, DATE = date, VALUE = value} );
}

此代码将通过DATE 为我提供每个USER 的最新结果。

但是 LINQ 查询是从用户那里选择所有数据,然后我在 foreach 循环中得到了最新的数据。

有没有办法只获取LINQ查询中的最后一条数据,这样就不用每次都取所有用户数据了?


我试过这个:

var data = conn.SCOT_DADOS.OrderByDescending(x => x.DATE)
                          .GroupBy(r => r.USER)
                          .First()
                          .ToList();

然后将item 视为一个对象,而不是对其运行选择。

它为我提供了单个用户的所有数据,这不是我想要的。

可以做什么?


编辑 1:

如果我尝试交换 OrderByDescendingGroupBy,则会收到此错误:

错误 CS1061 'IGrouping' 不包含 'DATE' 的定义并且没有扩展方法 'DATE' 接受第一个 可以找到“IGrouping”类型的参数(是 您缺少 using 指令或程序集引用?)


编辑 2:

这是一些示例数据(列名不一样,因为我为问题翻译了它们):

根据提供的数据,我会得到结果:

【问题讨论】:

  • 尝试交换顺序和组。
  • 我收到一个错误。我会补充这个问题。
  • @Phiter Fernandes - 请解释一下您的意思。添加示例输入和结果数据会有所帮助
  • User 是一个类还是仅仅是一个属性。如果您想订购已订购的列表,请使用:myList.OrderBy(o => o.MyProperty).ThenBy(o => o.OtherProperty)

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


【解决方案1】:

如果 (USER, DATE) 对的组合是唯一的(在查看样本数据时似乎就是这种情况),则可以将要求缩减为

如果没有其他记录具有相同的 USER 和更晚的 DATE,则返回每条记录

可以翻译成以下 LINQ 查询:

var result = conn.SCOT_DADOS
    .Where(r => !conn.SCOT_DADOS.Any(r2 => r2.USER == r.USER && r2.Date > r.Date))
    // end of Db Query 
    .AsEnumerable()
    .Select(r => new
    {
        Name = svc.GetUserName(r.User),
        Value = r.Value,
        Date = r.Date.ToString("dd/MM/yyyy HH:mm:ss")
    }).ToList(); 

【讨论】:

  • 我也可以使用主键来做到这一点。最新日期也将是最新的 ID。会不会更安全?
  • 好吧,如果你可以依赖它(我猜它是自动编号)。我宁愿把它作为安全检查包括在内——比如r2 => r2.USER == r.USER && (r2.Date > r.Date || (r2.Date == r.Date && r2.Id > r.Id))
  • 它什么也没返回
  • 好吧,在我的 EF 测试环境中的类似表上发布之前,我已经尝试过了,它正在返回数据。老实说,我不知道为什么它不适合你。
  • 我的错,我看错了变量。这确实奏效了!只是为了多打扰你一点。如何按值降序排列结果?
【解决方案2】:

我有点困惑,但从您对First() 的尝试来看,您的意思是:

conn.SCOT_DADOS.GroupBy(item => item.User)
               .Select(grp => grp.OrderByDescending(i => t.Date).First());

这将检索每个 User 只检索它的最新记录


仅交换GroupByOrderByDescending 是不够的,您需要Select 的原因是,一旦您对数据进行分组,您的可枚举对象就是IEnumerable<IGrouping<User,YourType>>。每个IGrouping 本身实际上就是一个集合,因此您只需要Select 即可从中获得您想要的一项。

另一种方法是将Select替换为:

.SelectMany(grp => grp.OrderByDescending(i => t.Date).Take(1))

IMO 第一个更干净,但第二个是在每个用户需要 N 个第一个项目的情况下


在上面的查询中,您还可以在foreach 循环中添加您所拥有的内容:

conn.SCOT_DADOS.GroupBy(item => item.User)
           .Select(grp => grp.OrderByDescending(i => t.Date).First())
           .AsEnumerable()
           .Select(item => new {
               Name = svc.GetUserName(item.User),
               Value = item.Value,
               Date = item.Date.ToString("dd/MM/yyyy HH:mm:ss")
           }).ToList();

AsEnumerable() 的使用是在最后一个 Select() 使用 Oracle 数据库不知道的 GetUserName 方法之前调用要对数据库执行的查询

IMO 将 DateTime 表示为字符串不是一个好方法..


更新 - 你得到的错误:

Oracle 11.2.0.3.0 不支持应用

对于这个版本的Oracle,它似乎不支持GroupBySelect via linq。见Linq to Entities Group By (OUTER APPLY) “oracle 11.2.0.3.0 does not support apply”。 那里的一个答案建议为此在数据库中创建一个视图,然后使用 linq 来选择该视图。这就是我的目标

【讨论】:

  • 我现在正在尝试您的解决方案。我将 DateTime 表示为字符串,因为它将显示给用户。
  • 它给了我方法'First'只能用作最终查询操作。请考虑在此实例中使用“FirstOrDefault”方法。
  • 另外,我不得不改成OrderByDescending(i => i.Date)
  • @PhiterFernandes - 是 ReSharper 这么说的吗?...我通常更喜欢使用 FirstOrDefault 以避免在空集合的情况下出现异常 - 但因为这是 @ 987654343@ 每个内部集合中至少有 1 个项目 - 所以首先也可以
  • 不,我没有 ReSharper。这是一个执行错误。
【解决方案3】:

试试这个

conn.SCOT_DADOS.GroupBy(x => x.User).Select(x => new
                {
                    User = x.Key,
                    Date = list.Where(y => y.User == x.Key).Max(y => y.Date)
                });

【讨论】:

    猜你喜欢
    • 2012-12-24
    • 2023-03-13
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2023-03-21
    • 2020-12-28
    相关资源
    最近更新 更多