按用户排序,然后选择最大日期

时间:2016-10-13 11:27:52

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

我有这个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} );
}

此代码会根据DATEUSER提供最新结果。

但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'类型的参数(是   你错过了使用指令或程序集引用?)

编辑2:

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

enter image description here

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

enter image description here

3 个答案:

答案 0 :(得分: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只需要你想要的1个项目。

另一种方法是将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()之前调用要对数据库执行的查询,GetUserName使用DateTime方法,而该方法是不知道的。 Oracle数据库

GroupBy表示为字符串的IMO不是一个好方法..

更新 - 您收到的错误:

  

Oracle 11.2.0.3.0不支持应用

对于此版本的Oracle,它似乎不支持Select通过linq undefined is not a function (evaluating '_this3.refs.Second.focus()') 。见Linq to Entities Group By (OUTER APPLY) “oracle 11.2.0.3.0 does not support apply”。 建议在数据库中为此创建一个视图,然后使用linq选择该视图。这就是我要去的地方

答案 1 :(得分:2)

如果(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(); 

答案 2 :(得分:0)

试试这个

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)
                });