LINQ查询多个聚集(LINQ query with multiple aggregates)

2019-08-17 17:04发布

我将如何创建等效的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

Answer 1:

你不能有效地选择在香草LINQ多个聚集到对象。 您可以执行多个查询,当然,但根据您的数据源上可能是低效的。

我有一个框架,这个我称之为“推LINQ”科佩斯 - 它只是一个爱好(我和Marc Gravell),但我们认为它工作得很好。 它可作为的一部分MiscUtil ,你可以在读到它上我的博客文章 。

这看起来有点奇怪 - 因为您可以定义你想要的结果去为“期货”,然后通过查询推数据,然后检索结果 - 但一旦你让你的头圆它,它的罚款。 我很想听听你是如何得到它 - 如果你使用它,请寄给我的skeet@pobox.com。



Answer 2:

单枚举产生两个最大和最小(并且要在那里扔任何其他聚合)。 这是在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);


Answer 3:

这是可以做到与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?)) 
    }
);

您还需要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;
}


文章来源: LINQ query with multiple aggregates