14

我有Measurement具有相关属性CreationTime(日期时间)和Reference(字符串)以及其他一些值的对象。

我想写一个有效的 linqDbContext查询

  • 按给定分组我的Measurement对象Reference
  • 按组CreationTime中第一个的属性或属性Measurement的平均值对组进行排序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正确选择“最近”的 s 组?

我将 Entity Framework 4.4 与 MySQL 数据库(MySql Connector/Net 6.6.4)一起使用。这个例子被简化了,我可以更详细地介绍和/或在必要时给出一个例子。

谢谢!

4

4 回答 4

15

它是方法语法(我发现它更容易阅读)但这可能会做到

更新了帖子评论

使用.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();
于 2013-03-22T14:01:32.880 回答
2

您可以尝试先将 GroupBy 和 Take 的结果转换为 Enumerable 然后处理其余部分(基于 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]
于 2014-03-31T09:53:44.963 回答
1

尝试移动order byafter group 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();
于 2013-03-22T13:50:15.733 回答
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 )
                   }

要按第一个测量创建时间对组进行排序(请注意,您应该对测量进行排序;如果您想要最早的 CreationTime 值,请将“g.SomeProperty”替换为“g.CreationTime”):

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

要按平均 CreationTime 对组进行排序,请使用 DateTime 结构的 Ticks 属性:

var refGroupsOrderedByAvgCreationTimeQuery = limitedQuery.OrderBy( lq => lq.RecentMeasurements.Average( g => g.CreationTime.Ticks ) );
于 2013-03-26T23:09:51.150 回答