2011-02-06 162 views
0

如何使用Linq选择最接近指定日期的记录?这是针对具有日期,产品ID,位置ID和余额的交易表。Linq选择最接近日期的记录

考虑到这些要求:

  • 如果有几个在指定日期
  • 选择最接近的现有交易,如果有没有在指定日期
  • 选择当天最后一笔交易显示的多个地点的平衡(例如仓库) - 每个仓库将有单独的交易
  • 显示多个产品的余额 - 每个产品将具有单独的交易

表数据:

// code 
Id, TransDateTime, ProductId, WarehouseId, Balance 
1, 1-Jan-2011 00:00, 1,   1,   100 
2, 1-Jan-2011 00:00, 1,   2,   10 
3, 2-Jan-2011 00:00, 1,   1,   150 
4, 3-Jan-2011 00:00, 1,   2,   25 
5, 3-Jan-2011 00:00, 2,   1,   333 
6, 7-Jan-2011 00:00, 1,   1,   149 
7, 7-Jan-2011 01:00, 1,   2,   30 
8, 7-Jan-2011 02:00, 1,   2,   35 

考试日期和输出

Date: 1-Jan would output: 
1, 1-Jan-2011 00:00, 1,   1,   100 
2, 1-Jan-2011 00:00, 1,   2,   10 

Date: 3-Jan would output: 
3, 2-Jan-2011 00:00, 1,   1,   150 
4, 3-Jan-2011 00:00, 1,   2,   25 
5, 3-Jan-2011 00:00, 2,   1,   333 
// product 1, warehouse 1 wasn't sold on the 3rd 
// so the row from 2-Jan is returned 

Date: 7-Jan would output: 
5, 3-Jan-2011 00:00, 2,   1,   333 
6, 7-Jan-2011 00:00, 1,   1,   149 
9, 7-Jan-2011 02:00, 1,   2,   35 
// product 2, warehouse 1 wasn't sold on the 7th 
// so the row from 3-Jan is returned 
// product 1, warehouse 2 was sold twice on the 7th 
// so the later one is used 

我认为这将需要组进行分组(产品 - >仓库 - >日期)或类似的。它超越了我的linq能力!

回答

5

步骤:
1)筛选出inputDate
2)按产品和仓库
3)在每个组中记录的组其余之后发生的交易找到最近的事务
4)格式的结果对象

简单的实现:

DateTime inputDate = ...; 
var result = transactions 
      .Where(t => t.TransDateTime.Date <= inputDate.Date) 
      .GroupBy(t => new {t.ProductId, t.WarehouseId}) 
      .Select(x => new { 
       x.Key, 
       LastTransaction = x.OrderByDescending(t => t.TransDateTime).First(), 
      }) 
      .Select(x => new { 
       Id = x.LastTransaction.Id, 
       Date = x.LastTransaction.TransDateTime, 
       ProductId = x.Key.ProductId, 
       WarehouseId = x.Key.WarehouseId, 
       Balance = x.LastTransaction.Balance, 
      }); 

如果你想要一些优化,你可以考虑实施MaxBy用于IEnumerable的扩展方法来代替x.OrderByDescending(t => t.TransDateTime).First()。如果您有很多交易,它会提高性能,因为它是O(n)而不是O(n log n)MaxBy实现可以在这里采用,例如:Simple LINQ question in C#

+0

+1似乎工作到目前为止,谢谢,只是一个很容易修复的错误:'方法'第一'只能用作最终查询操作。请考虑在这个实例中使用方法'FirstOrDefault'。' – 2011-02-07 00:35:12