Linq选择最接近日期的记录

JK.*_*JK. 0 c# linq

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

鉴于这些要求:

  • 如果在指定日期有多个交易,请选择当天的最后一笔交易
  • 如果指定日期没有,则选择最接近的先前交易
  • 在多个位置(例如仓库)显示余额 - 每个仓库将具有单独的交易
  • 显示多个产品的余额 - 每个产品都有单独的交易

表数据:

// 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
Run Code Online (Sandbox Code Playgroud)

测试日期和输出

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
Run Code Online (Sandbox Code Playgroud)

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

Sno*_*ear 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,
          });
Run Code Online (Sandbox Code Playgroud)

如果您想要进行一些优化,可以考虑实现要替换的MaxBy扩展方法.如果您有许多交易,它将提高性能,因为它代替.这里可以实现实现,例如:C#中的简单LINQ问题IEnumerablex.OrderByDescending(t => t.TransDateTime).First()O(n)O(n log n)MaxBy