6

如何创建等效的 Linq To Objects 查询?

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
4

3 回答 3

4

产生最小值和最大值的单个枚举(以及您想要放入其中的任何其他聚合)。这在 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);
于 2008-09-30T20:55:41.800 回答
2

您无法在 vanilla LINQ to Objects 中有效地选择多个聚合。当然,您可以执行多个查询,但这可能效率低下,具体取决于您的数据源。

我有一个框架来解决这个问题,我称之为“Push LINQ”——这只是一种爱好(对我和 Marc Gravell 来说),但我们相信它工作得很好。它作为MiscUtil的一部分提供,您可以在我的博客文章中了解它

它看起来有点奇怪 - 因为您将希望结果的位置定义为“期货”,然后通过查询推送数据,然后检索结果 - 但是一旦您了解它,就可以了。我很想听听您如何使用它 - 如果您使用它,请通过 skeet@pobox.com 给我发邮件。

于 2008-09-30T19:59:40.467 回答
0

可以使用 LINQ-to-Objects 进行多个聚合,但这有点难看。

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;
}
于 2010-01-19T15:55:33.960 回答