Linq - 在一个查询中计算多个平均值
我正在尝试将一些 SQL 查询转换为 Linq 以避免多次访问数据库。
我尝试转换的旧 SQL 是这样的:
SELECT
AVG(CAST(DATEDIFF(ms, A.CreatedDate, B.CompletedDate) AS decimal(15,4))),
AVG(CAST(DATEDIFF(ms, B.CreatedDate, B.CompletedDate) AS decimal(15,4)))
FROM
dbo.A
INNER JOIN
dbo.B ON B.ParentId = A.Id
所以我创建了两个 C# 类:
class B
{
public Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime CompletedDate { get; set; }
}
class A
{
public Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
public List<B> BList { get; set; }
}
并且我有一个要查询的 List
对象。 它是从数据库填充的,因此列表中的每个 A 都有一个包含 B 负载的子列表。 我想使用 Linq-to-objects 来查询此列表。
因此,我需要使用 Linq 来获取 A 的开始和其子 B 的完成之间的平均时间,以及每个 B 的开始和完成之间的平均时间。 我没有编写原始 SQL,所以我不完全确定它是否达到了预期的效果!
我有几个平均值需要计算,因此我想在一个神奇的 Linq 查询中完成所有这些操作。 这可能吗?
I'm trying to convert some SQL queries into Linq to avoid multiple trips to the database.
The old SQL I'm trying to convert does:
SELECT
AVG(CAST(DATEDIFF(ms, A.CreatedDate, B.CompletedDate) AS decimal(15,4))),
AVG(CAST(DATEDIFF(ms, B.CreatedDate, B.CompletedDate) AS decimal(15,4)))
FROM
dbo.A
INNER JOIN
dbo.B ON B.ParentId = A.Id
So I've created two C# classes:
class B
{
public Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime CompletedDate { get; set; }
}
class A
{
public Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
public List<B> BList { get; set; }
}
And I've got a List<A>
object that I want to query. It's populated from the database, so each A in the list has a sub-list with a load of Bs. I want to use Linq-to-objects to query this list.
So I need to use Linq to get the average time between an A's start and the completion of its child Bs, and the average time between each B's start and completion. I didn't write the original SQL so I'm not entirely sure it does what it's supposed to!
I've got several of these averages to calculate, so I'd like to do them all inside one magical Linq query. Is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
更有趣的问题是如何在服务器上执行此类操作,例如将以下查询转换为 LINQ to SQL。
但是,如果您使用 LINQ to Objects,则尝试将其塞入一个查询中是没有意义的。 分别写出聚合即可:
换句话说:
我理解对了吗?
编辑:David B 也做出了类似的回答。 我忘记将 TimeSpan 转换为 Average 方法支持的简单数字类型。 使用总毫秒/秒/分钟或任何合适的比例。
The more interesting question would be how to do such a thing on the server, for example to make the following query translate to LINQ to SQL.
But there's no point trying to cram it into one query if you're using LINQ to Objects. Just write the aggregates separately:
In other words:
Did I understand right?
Edit: David B answered similarly. I forgot to convert the TimeSpan to a simple numeric type supported by the Average method. Use TotalMilliseconds/Seconds/Minutes or whatever scale is appropriate.
Sql 和 Linq 在某些方面有所不同。 Sql 有隐式分组 - 将所有这些分组为一组。 在 linq 中,人们可以通过引入一个常量来进行分组来伪造隐式分组。
Sql and Linq differ on certain points. Sql has implicit grouping - take all of these and make one group. In linq, one may fake implicit grouping by introducing a constant to group on.
让我们从获取 B 的开始和结束之间的平均时间开始:
1) 您首先需要每个 B 对象的开始和结束之间的时间差,因此您可以执行以下操作:
2) 您现在需要获取其平均值。 您可以使用 lambda 表达式来完成此操作:
您现在可以执行相同的操作来获取 A 的开始和 B 的完成之间的平均时间,如下所示:
1) 获取 A 的开始日期和每个 B 的完成日期的时间差:
2) 获取这些时间差的平均值与上面的完全一样:
你就完成了。 我希望这个对你有用。 请注意,此代码尚未经过测试。
编辑:请记住,LINQ 使用 Lamda 表达式,但更多的是语法糖(对实现了解不多,所以我希望您不要反对我)。 您还可以将我提供的实现包装在方法中,以便您可以针对 A 对象列表多次调用它们。
Lets start by getting the average time between B's start and finish:
1) You first need the time difference between the start and finish of each B object so you would do this:
2) You now need to get the average of this. You can do this by using lambda expressions:
You can now do the same thing to get the average time between A's start and B's finish as follows:
1)Get the time difference for A's start date and each of B's completion date:
2) Get the average of these time differnces exactly like the one above:
And you're done. I hope that this helps. Please note that this code has not been tested.
EDIT: Remember that LINQ uses Lamda Expressions but is more of syntactic sugar (don't know much about the implementation so I hope you don't hold it against me). And also you could wrap the implementaions I provide in methods so that you can call them multiple times for a List of A objects.