我将如何创建等效的Linq To Objects查询?LINQ查询与多个聚合
SELECT MIN(CASE WHEN p.type = "In" THEN p.PunchTime ELSE NULL END) AS EarliestIn,
MAX(CASE WHEN p.type = "Out" THEN p.PunchTime ELSE NULL END) AS LatestOUt
FROM Punches p
我将如何创建等效的Linq To Objects查询?LINQ查询与多个聚合
SELECT MIN(CASE WHEN p.type = "In" THEN p.PunchTime ELSE NULL END) AS EarliestIn,
MAX(CASE WHEN p.type = "Out" THEN p.PunchTime ELSE NULL END) AS LatestOUt
FROM Punches p
你不能在vanilla LINQ to Objects中有效地选择多个聚合。当然,您可以执行多个查询,但根据您的数据源,这可能效率很低。
我有一个框架,对付这个我称之为“推LINQ” - 这只是一个业余爱好(对于我和Marc Gravell),但我们相信它工作得很好。它作为MiscUtil的一部分提供,您可以在my blog post on it中阅读。
它看起来有点奇怪 - 因为您定义了希望结果作为“期货”的位置,然后通过查询推送数据,然后检索结果 - 但是一旦您将头转过来,就没有问题。我很想听听你如何继续使用它 - 如果你使用它,请发邮件到[email protected]。
单枚枚举产生最小值和最大值(以及任何其他想要抛入的聚合)。这在vb.net中更容易。
我知道这不处理空案。这很容易添加。
List<int> myInts = new List<int>() { 1, 4, 2, 0, 3 };
var y = myInts.Aggregate(
new { Min = int.MaxValue, Max = int.MinValue },
(a, i) =>
new
{
Min = (i < a.Min) ? i : a.Min,
Max = (a.Max < i) ? i : a.Max
});
Console.WriteLine("{0} {1}", y.Min, y.Max);
这是一个手册,但它对我来说已经足够了。当你打断linq时,你很快就会回到仅仅是foreach外观的语法快捷方式。 – 2008-09-30 21:54:23
可以使用LINQ到对象进行多个聚合,但它有点难看。
var times = punches.Aggregate(
new { EarliestIn = default(DateTime?), LatestOut = default(DateTime?) },
(agg, p) => new {
EarliestIn = Min(
agg.EarliestIn,
p.type == "In" ? (DateTime?)p.PunchTime : default(DateTime?)),
LatestOut = Max(
agg.LatestOut,
p.type == "Out" ? (DateTime?)p.PunchTime : default(DateTime?))
}
);
您还需要DateTime的Min和Max函数,因为这些函数是不可用的标准。
public static DateTime? Max(DateTime? d1, DateTime? d2)
{
if (!d1.HasValue)
return d2;
if (!d2.HasValue)
return d1;
return d1.Value > d2.Value ? d1 : d2;
}
public static DateTime? Min(DateTime? d1, DateTime? d2)
{
if (!d1.HasValue)
return d2;
if (!d2.HasValue)
return d1;
return d1.Value < d2.Value ? d1 : d2;
}
谢谢Jon。到目前为止,Linq最困难的部分之一就是搞清楚你能做什么,不能做什么。一旦我对标准方法更加适应,我一定会看看你的Push技术。 – 2008-09-30 20:07:07