[英]Entity Framework - Linq query with order by and group by
I have Measurement
Objects with the relevant Properties CreationTime
(DateTime) and Reference
(String) and some other values. 我有Measurement
Objects使用相关的Properties CreationTime
(DateTime)和Reference
(String)以及其他一些值。
I'd like to write an efficient linq query to a DbContext
that 我想为DbContext
写一个有效的linq查询
Measurement
objects by a given Reference
按给定的Reference
我的Measurement
对象进行分组 CreationTime
Property of the first Measurement
from the group or the average of the CreationTime
properties 由任一订单组CreationTime
第一性能Measurement
从上述组或上述的平均CreationTime
属性 numOfEntries
将查询限制为最新的numOfEntries
(In a later step i calculate averaged values over these returned groups, but i guess that's not relevant for my problem.) (在后面的步骤中,我计算这些返回组的平均值,但我猜这与我的问题无关。)
The DbContext itself has a DbSet<Measurement>
called Measurements
holding all Measurement
objects. DbContext本身有一个DbSet<Measurement>
称为Measurements
所有Measurement
对象。
I came up with the following query, that results in a List of groups that is ordered correctly but is missing some groups in between. 我提出了以下查询,这会产生一个正确排序但缺少某些组的组列表。
var groupByReference = (from m in context.Measurements
orderby m.CreationTime
group m by new { m.Reference } into g
select g).Take(numOfEntries).ToList();
How do I select the "most recent" groups of Measurement
s correctly? 如何正确选择“最新” Measurement
组?
I'm using Entity Framework 4.4 with a MySQL Database (MySql Connector/Net 6.6.4). 我正在使用Entity Framework 4.4和MySQL数据库(MySql Connector / Net 6.6.4)。 This example is simplified, i can go into more detail and/or give an example if necessary. 这个例子是简化的,我可以进一步详细说明和/或在必要时给出一个例子。
Thanks! 谢谢!
It's method syntax (which I find easier to read) but this might do it 这是方法语法(我觉得更容易阅读),但这可能会这样做
Updated post comment 更新了帖子评论
Use .FirstOrDefault()
instead of .First()
使用.FirstOrDefault()
而不是.First()
With regard to the dates average, you may have to drop that ordering for the moment as I am unable to get to an IDE at the moment 关于日期平均值,您可能不得不暂时删除该顺序,因为此刻我无法访问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();
You can try to cast the result of GroupBy and Take into an Enumerable first then process the rest (building on the solution provided by NinjaNye 您可以先尝试将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);
Your sql query would look similar (depending on your input) this 您的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]
Try moving the order by
after group by
: 尝试order by
group by
后移动order 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();
Your requirements are all over the place, but this is the solution to my understanding of them: 您的要求到处都是,但这是我理解它们的解决方案:
To group by Reference property: 要按引用属性分组:
var refGroupQuery = (from m in context.Measurements
group m by m.Reference into refGroup
select refGroup);
Now you say you want to limit results by "most recent numOfEntries" - I take this to mean you want to limit the returned Measurements... in that case: 现在你说你想用“最近的numOfEntries”来限制结果 - 我认为你想要限制返回的测量值......在这种情况下:
var limitedQuery = from g in refGroupQuery
select new
{
Reference = g.Key,
RecentMeasurements = g.OrderByDescending( p => p.CreationTime ).Take( numOfEntries )
}
To order groups by first Measurement creation time (note you should order the measurements; if you want the earliest CreationTime value, substitue "g.SomeProperty" with "g.CreationTime"): 要通过第一次测量创建时间来订购组(请注意您应该订购测量;如果您想要最早的CreationTime值,请将“g.SomeProperty”替换为“g.CreationTime”):
var refGroupsOrderedByFirstCreationTimeQuery = limitedQuery.OrderBy( lq => lq.RecentMeasurements.OrderBy( g => g.SomeProperty ).First().CreationTime );
To order groups by average CreationTime, use the Ticks property of the DateTime struct: 要按平均CreationTime对组进行排序,请使用DateTime结构的Ticks属性:
var refGroupsOrderedByAvgCreationTimeQuery = limitedQuery.OrderBy( lq => lq.RecentMeasurements.Average( g => g.CreationTime.Ticks ) );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.