C# LINQ Select记录相隔X分钟

C# LINQ Select记录相隔X分钟,c#,sql,linq,C#,Sql,Linq,我有一个简单的表格,可以记录入职日期。我想选择相隔X分钟的记录 IMAGE_LOCATION IMAGE DATE ============== ============= 2227.jpg 08/03/2014 22:27:47 2228.jpg 08/03/2014 22:28:48 2229.jpg 08/03/2014 22:59:49 2230.jpg 08/03/2014 23:12:50 2231.jpg 08/03/2014 23:29:49 从

我有一个简单的表格,可以记录入职日期。我想选择相隔X分钟的记录

IMAGE_LOCATION  IMAGE DATE
============== =============
2227.jpg    08/03/2014 22:27:47
2228.jpg    08/03/2014 22:28:48
2229.jpg    08/03/2014 22:59:49
2230.jpg    08/03/2014 23:12:50
2231.jpg    08/03/2014 23:29:49
从上面的示例中,我希望查询返回至少相隔X分钟的项目,比如说30分钟。因此,从2227.jpg上面的列表中,2229.jpg和2231.jpg将仅返回

这是我到目前为止只返回最新的图像,但是我需要最新的图像,但记录之间至少间隔30分钟

using (var db = new GibFrontierEntities())
{
    var result = (from u in db.CCTV_IMAGES.OrderByDescending(u => u.ImageDate)
                  select u).Take(rows);
    return result.ToList();
}

如前所述,这可以通过迭代轻松实现。但是,如果您真的需要处理LINQ表达式,下面是一个快速而脏的示例,它将返回相隔30分钟的日期:

List<DateTime> dateLlist = new List<DateTime>();

        dateLlist.Add(new DateTime(2014, 1, 1, 1, 0, 0, 0));
        dateLlist.Add(new DateTime(2014, 1, 1, 1, 10, 0, 0));
        dateLlist.Add(new DateTime(2014, 1, 1, 1, 45, 0, 0));

        DateTime previousTime = new DateTime();
        bool shouldAdd = false;
        List<DateTime> newList = dateLlist.Where(x =>
        {
            shouldAdd = (previousTime == DateTime.MinValue || previousTime.AddMinutes(30) < x);
            previousTime = x;
            return shouldAdd;
        }).ToList();  

这是一个快速的尝试,旨在实现您所要求的,经过测试并在.NET 4中工作的LINQ解决方案:

var list = db.CCTV_IMAGES.OrderByDescending(u => u.ImageDate);
return list.Where((d, i) =>
        {
            //Look ahead to compare against the next if it exists.
            if (list.ElementAtOrDefault(i + 1) != null)
            {
                return d.ImageDate.Subtract(list.ElementAtOrDefault(i + 1).ImageDate).TotalMinutes > 30;
            }

            //Look behind to compare against the previous if this is the last item in the list.
            if (list.ElementAtOrDefault(i - 1) != null)
            {
                return list.ElementAtOrDefault(i - 1).ImageDate.Subtract(d.ImageDate).TotalMinutes > 30;
            }

            return false;
        }).ToList();
根据评论和更明确的要求定义:

因为你在下面的评论中说,你将有1个项目一分钟,你以前说过你需要它们至少30分钟分开,你会考虑简化逻辑来抓取列表中的每第三十个项目吗?

return list.Where((d, i) => i % 30 == 0);
您可以使用来实现您想要的:

using (var db = new GibFrontierEntities())
{
    var images = db.CCTV_IMAGES;
    var result = images
        .SelectMany(i => images,
            (first, second) => new { First = first, Second = second })
        .Where(i => i.First != i.Second)
        .Where(i => Math.Abs(
            EntityFunctions
                .DiffMinutes(i.First.ImageDate, i.Second.ImageDate)) >= 30)
        .Select(i => i.First)
        .Distinct()
        .OrderByDescending(i => i.ImageDate)
        .Take(rows)
        .ToList();
    return result;
}

使用一个简单的foreach非常容易,您甚至不应该尝试为它编写LINQ one liner。@GertArnold我想他会进行此预枚举,以便在SQL server上执行此操作。但你是对的,因为他们总是用最后30分钟,所以在C中可能比在SQLLast中容易,因为最后两条记录也相隔30分钟。为什么不选择它们?@SergeyBerezovskiy倒数第二个项目距离前面的项目不到30分钟。最后一个项目比最后一个包含的项目晚30多分钟,因此它被包含。在DB端创建一个存储过程,使用光标遍历查询并包含适当的项目。Entity Framework不知道如何将其转换为SQL查询。这似乎引发了一个异常。异常是什么?很抱歉,我目前无法测试代码。这不是有效的LINQ查询。传递给Where方法的lambda表达式只接受一个参数。啊,是的,你完全正确。我完全忘记了重载的Where方法,该方法包括源元素的索引。@Tommy我的更新现在还将包括列表的最后一项,前提是它的前身是30分钟前的。如果您不希望包含该条件,只需将其删除即可。SelectMany的重载是什么?这将返回至少还有一个时间超过X分钟的每个项目。那是不对的。例如,示例中的第二个项目距它有30分钟以上的项目,但它前面的项目在阈值内,因此它被排除在外。您需要将每个项目与*之前的项目配对,而不是列表中的所有其他项目。我在回答中提供了指向特定重载的链接。