在SQL中,您可以在单个数据库查询中表达多个聚合,如下所示:
SELECT MIN(p.x), MAX(p.x), MIN(p.y), MAX(p.y)
FROM Places p JOIN Logs l on p.Id = l.PlaceId
WHERE l.OwnerId = @OwnerId
是否可以使用Linq-to-Entities做同等的事情?我发现similar question表示Linq-to-SQL不可能,但我想我不需要四次往返数据库就可以完成上述操作。
答案 0 :(得分:24)
假设您有以下SQL语句:
select sum(A), max(B), avg(C) from TBL group by D
在C#中尝试:
from t in table
group t by D
into g
select new {
s = g.Sum(x => x.A),
m = g.Max(x => x.B),
a = g.Average(x => x.C)
}
- 或在VB中: -
from t in TBL
group t by key = D
into g = group
select s = g.Sum(function(x) x.A),
m = g.Max(function(x) x.B),
a = g.Average(function(x) x.C)
显而易见的,在VB中将是:
aggregate t in TBL into s = Sum(t.A), m = Max(t.B), a = Average(t.C)
虽然它会给出相同的结果,但它会发出更高的成本,因为它发出多个SQL select语句,每个聚合函数一个,即它将在多个传递中运行。第一种语法提供了一个(相当复杂但有效)的SQL语句,它对数据库进行单次传递。
PS。如果您没有要分组的键(即,您需要一行作为结果,覆盖整个数据集),请使用常量,如下所示:
from t in TBL
group t by key = 0
into g = group
select s = g.Sum(function(x) x.A),
m = g.Max(function(x) x.B),
a = g.Average(function(x) x.C)
答案 1 :(得分:2)
我没有你的数据库,但是这个(使用Northwind.mdb的“默认”EDMX模型 - 运行新模型向导后没有变化)在LINQPad中作为一个查询运行:
var one = from c in Customers
where c.PostalCode == "12209"
select new
{
Id = c.Orders.Max(o => o.OrderID),
Country = c.Orders.Min(o => o.ShipCountry)
};
one.Dump();
根据您的评论更新:
var two = from c in Customers
where c.PostalCode == "12209"
from o in c.Orders
group o by o.Customer.PostalCode into g
select new
{
PostalCode = g.Key,
Id = g.Max(o => o.OrderID),
Country = g.Min(o => o.ShipCountry)
};
two.Dump();
答案 2 :(得分:0)
不幸的是答案似乎是否。
如果有人能证明不然,我会很乐意给他们接受的答案。
编辑
我找到了一种使用Entity SQL执行此操作的方法。我不确定它是最好的方式,但因为它似乎只是 方式,所以默认情况下它可能是最好的:)
var cmdText = "SELECT MIN(p.x), MAX(p.x), MIN(p.y), MAX(p.y) " +
"FROM Places AS p JOIN Logs AS l ON p.Id = l.PlaceId " +
"WHERE l.OwnerId==123";
var results = CreateQuery<DbDataRecord>(cmdText)
var row = results.First();
var minX = (double)row[0];
var maxX = (double)row[1];
var minY = (double)row[2];
var maxY = (double)row[3];
以上并不完全是我正在使用的代码。对于没有连接的更简单的情况,这里是生成的SQL,显示只有一次数据库之旅:
SELECT
1 AS [C1],
[GroupBy1].[A1] AS [C2],
[GroupBy1].[A2] AS [C3],
[GroupBy1].[A3] AS [C4],
[GroupBy1].[A4] AS [C5]
FROM ( SELECT
MIN([Extent1].[X1]) AS [A1],
MAX([Extent1].[X1]) AS [A2],
MAX([Extent1].[Y1]) AS [A3],
MIN([Extent1].[Y1]) AS [A4]
FROM [dbo].[Edges] AS [Extent1]
WHERE [Extent1].[PlaceId] = 123
) AS [GroupBy1]
如果有人找到更优雅的解决方案,我会给他们接受的答案。
编辑2
感谢Costas发现使用纯Linq的a great solution to this problem。