简体   繁体   English

Linq选择最接近日期的记录

[英]Linq select records closest to date

How do you use Linq to select the record that is closest to a specified date? 如何使用Linq选择最接近指定日期的记录? This is for a transaction table that has a date, product id, location id, and balance. 这是针对具有日期,产品ID,位置ID和余额的交易表。

Given these requirements: 鉴于这些要求:

  • Select the last transaction of the day if there were several on the specified day 如果指定的日期有几笔交易,请选择当天的最后一笔交易
  • Select the closest prior transaction if there were none on the specified day 如果指定日期没有最近的交易,请选择最近的交易
  • Show the balance in multiple locations (eg warehouses) - each warehouse will have separate transactions 在多个位置(例如仓库)显示余额-每个仓库将有单独的交易
  • Show the balance for multiple products - each product will have separate transactions 显示多种产品的余额-每个产品都有单独的交易

Table data: 表格数据:

// 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

Test dates and outputs 测试日期和输出

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

I think it's going to require grouping of groups (product -> warehouse -> date) or similar. 我认为这将需要对分组进行分组(产品->仓库->日期)或类似的分组。 Its beyond my linq ability! 它超出了我的能力!

Steps: 脚步:
1) Filter out transactions that happened after inputDate 1)过滤掉inputDate之后发生的交易
2) Group rest of transactions by product and warehouse 2)按产品和仓库将其余交易分组
3) In each group find most recent transaction 3)在每个组中找到最近的交易
4) Format result object 4)格式化结果对象

Straightforward implementation: 简单实施:

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,
          });

If you want some optimizations you can consider implementing MaxBy extension method for IEnumerable to replace x.OrderByDescending(t => t.TransDateTime).First() . 如果要进行一些优化,可以考虑为IEnumerable实现MaxBy扩展方法,以替换x.OrderByDescending(t => t.TransDateTime).First() It will improve performance if you have many transactions since it is O(n) instead of O(n log n) . 如果您有很多事务,它将提高性能,因为它是O(n)而不是O(n log n) MaxBy implementation can be taken here for example: Simple LINQ question in C# MaxBy实现可以在这里举例: C#中的简单LINQ问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM