2013-03-22 43 views
10

我有Measurement具有相关属性的对象CreationTime(DateTime)和Reference(String)以及其他一些值。实体框架 - Linq查询,按顺序排列并且组编号为

我想用一个给定的Reference

  • 订单的有效LINQ查询写入DbContext

    • 组我Measurement对象从该组的团体由第一MeasurementCreationTime物业或CreationTime属性的平均值
    • 将查询限制为最近的numOfEntries

    (在后面的步骤我计算平均超过这些返回群体的价值观,但我想这是不相关的我的问题。)

    的的DbContext本身具有DbSet<Measurement>称为Measurements持有所有Measurement对象。

    我想出了下面的查询,结果列出了正确排序但缺少一些组的列表。

    var groupByReference = (from m in context.Measurements 
              orderby m.CreationTime 
              group m by new { m.Reference } into g 
              select g).Take(numOfEntries).ToList(); 
    

    如何正确选择“最近”的Measurement组?

    我使用实体框架4.4与MySQL数据库(MySql连接器/网络6.6.4)。这个例子被简化了,如果需要的话,我可以进入更多的细节和/或给出一个例子。

    谢谢!

  • +1

    而不是计算“的创建时间的平均“,您是否考虑过从给定点计算时间跨度,然后确定这些时间跨度的平均值,然后根据给定点和平均时间跨度计算结果日期? – 2013-03-22 19:52:17

    回答

    0

    尝试移动order bygroup by

    var groupByReference = (from m in context.Measurements 
             group m by new { m.Reference } into g 
             order by g.Avg(i => i.CreationTime) 
             select g).Take(numOfEntries).ToList(); 
    
    +0

    我试过了,但得到一个错误,'DateTime'不能转换为'int'。我也用'int'属性进行了测试,得到了一个MySqlException异常,如'字段列表'中的未知列'GroupBy1.K2'“ – zufallsfund 2013-03-22 14:07:07

    9

    这是方法的语法(我觉得这更容易阅读),但这可能做到这一点

    更新后评论

    使用.FirstOrDefault()代替.First()

    关于日期平均水平,你可能不得不放弃该订货的时刻,因为我无法去一个IDE此刻

    var groupByReference = context.Measurements 
               .GroupBy(m => m.Reference) 
               .Select(g => new {Creation = g.FirstOrDefault().CreationTime, 
    //            Avg = g.Average(m => m.CreationTime.Ticks), 
                   Items = g }) 
               .OrderBy(x => x.Creation) 
    //       .ThenBy(x => x.Avg) 
               .Take(numOfEntries) 
               .ToList(); 
    
    +1

    感谢您的建议,但我得到了一个'NotSupportedException'尝试确定g.First()因为'g'不是最终的查询操作。尝试对'CreationTime'属性取平均值失败,因为它不是'int'。 – zufallsfund 2013-03-22 14:29:50

    +0

    我已经更新了我的答案,但我无法修复平均日期问题,直到遇到IDE – NinjaNye 2013-03-22 18:50:39

    +0

    感谢您的努力。在此期间我尝试了这种方法,并添加了一个“Ticks”属性,该属性将CreationTime存储为一个很长的时间,以便'.Average()'能够正常工作。现在,我正在获取MySQL异常,其中说明了'场列表'(平均)'中的'where子句''(FirstOrDefault)或'未知列'GroupBy1.K2'中的未知列'Distinct1.Reference'。是一个MySql连接器错误的可能原因呢? (我应该提到真正的查询有点复杂,我不直接查询DbSet,而是使用另一个查询作为源。) – zufallsfund 2013-03-26 10:01:24

    0

    你的要求是所有的地方,但是这是解决方案以我对他们的理解:

    要组通过参考属性:

    var refGroupQuery = (from m in context.Measurements 
          group m by m.Reference into refGroup 
          select refGroup); 
    

    现在你说你要限制由“最近numOfEntries”的结果 - 我认为这意味着要限制返回测量...在这种情况下:

    var limitedQuery = from g in refGroupQuery 
            select new 
            { 
             Reference = g.Key, 
             RecentMeasurements = g.OrderByDescending(p => p.CreationTime).Take(numOfEntries) 
            } 
    

    要订购的第一次测量创建时间组(注意:您应该测量;如果你想最早的创建时间值,substitue“g.SomeProperty”与“g.CreationTime”):

    var refGroupsOrderedByFirstCreationTimeQuery = limitedQuery.OrderBy(lq => lq.RecentMeasurements.OrderBy(g => g.SomeProperty).First().CreationTime); 
    

    要订购的平均CREATIONTIME组,使用的DateTime结构的蜱属性:

    var refGroupsOrderedByAvgCreationTimeQuery = limitedQuery.OrderBy(lq => lq.RecentMeasurements.Average(g => g.CreationTime.Ticks)); 
    
    1

    您可以尝试投的GroupBy的结果,并考虑到一ñ可枚举第一,然后处理其余部分(建筑由NinjaNye提供的解决方案

    var groupByReference = (from m in context.Measurements 
               .GroupBy(m => m.Reference) 
               .Take(numOfEntries).AsEnumerable() 
               .Select(g => new {Creation = g.FirstOrDefault().CreationTime, 
                  Avg = g.Average(m => m.CreationTime.Ticks), 
                   Items = g }) 
               .OrderBy(x => x.Creation) 
               .ThenBy(x => x.Avg) 
               .ToList() select m); 
    

    您的SQL查询将类似于(根据您的输入)这个

    SELECT TOP (3) [t1].[Reference] AS [Key] 
    FROM (
        SELECT [t0].[Reference] 
        FROM [Measurements] AS [t0] 
        GROUP BY [t0].[Reference] 
        ) AS [t1] 
    GO 
    
    -- Region Parameters 
    DECLARE @x1 NVarChar(1000) = 'Ref1' 
    -- EndRegion 
    SELECT [t0].[CreationTime], [t0].[Id], [t0].[Reference] 
    FROM [Measurements] AS [t0] 
    WHERE @x1 = [t0].[Reference] 
    GO 
    
    -- Region Parameters 
    DECLARE @x1 NVarChar(1000) = 'Ref2' 
    -- EndRegion 
    SELECT [t0].[CreationTime], [t0].[Id], [t0].[Reference] 
    FROM [Measurements] AS [t0] 
    WHERE @x1 = [t0].[Reference]