从开始日期和结束日期跨越天的数据创建趋势数据

本文关键字:数据 日期 创建 跨越 开始 结束 | 更新日期: 2023-09-27 18:31:40

我正在使用C#,NHibernate,Fluent NHibernate和LINQ(存储库模式)。

关于我想做什么的虚构故事

假设我有一个停车位,所以我有一辆车从日期到日期租用一个停车位。这将成为数据库中的一个条目。

我想找出过去 30 天内每天有多少辆汽车。因此,可以在趋势图中使用的数据。

描述

我拥有的是数据库中的条目,如下所示:

Entry:
--------
ID
StartDate
EndDate

我需要找出在一段时间内(比如last 30 days)有多少条目each day

如果我在数据库中说了这些数据:

ID | Start      | End
---|------------|----------
1  | 2013-01-01 | 2013-01-01
2  | 2013-01-02 | 2013-01-02
3  | 2013-01-02 | 2013-01-03 <-- NOTICE
4  | 2013-01-03 | 2013-01-03
5  | 2013-01-03 | 2013-01-05 <-- NOTICE
6  | 2013-01-04 | 2013-01-05

我的日期范围2013-01-012013-01-05

我除了结果:

Date       | Value | Entry IDs (not part of the result, only here for clarity)
-----------|-------|-----------
2013-01-01 | 1     | 1
2013-01-02 | 2     | 2 3
2013-01-03 | 3     | 3 4 5
2013-01-04 | 2     | 5 6
2013-01-05 | 2     | 5 6

我目前只按startdate分组然后获取数字,但现在这是无效的,因为这个新要求是随enddate一起添加的。

我可以在该范围内每天做一个,尝试找到与之匹配的条目,但我认为这对数据库或 Web 服务来说太昂贵了。

建议?

从开始日期和结束日期跨越天的数据创建趋势数据

也许是这样的:

var start = new DateTime(2013, 01, 01);
var end = DateTime(2013, 01, 05);
var q = d.Query()
         .Where(x =>
             x.Date >= start
             && end >= x.Date) // there you filter for range 
         .GroupBy(x => x.Date); // use .Day to group by day

开始时间和结束时间包括在内。

编辑

我发现了这个(实际上我在我的项目中有一个类似的案例):

var start = new DateTime(2013, 1, 1);
var end = new DateTime(2013, 1, 5);
var current = start;
var ranges = new List<DateTime>();
while (current <= end)
{
    ranges.Add(current);
    current = current.AddDays(1);
}
var res = ranges.Select(x => new
{
    date = x,
    entries = entries.Where(e => e.Start <= x && x <= e.End).ToList()
}).ToList();

尝试测试它,也许您可以适应您的情况(请注意,过滤从日期范围开始)。

可以使用适用于 .NET 的时间段库来计算趋势数据:

// ----------------------------------------------------------------------
class CarPeriod : DayTimeRange
{
  // --------------------------------------------------------------------
  public CarPeriod( int id, DateTime start, DateTime end ) :
    this( id, start, end.Date.AddDays( 1 ).Subtract( start.Date ).Days )
  {
  } // CarPeriod
  // --------------------------------------------------------------------
  public CarPeriod( int id, DateTime start, int days ) :
    base( start.Year, start.Month, start.Day, days )
  {
    Id = id;
  } // CarPeriod
  // --------------------------------------------------------------------
  public int Id { get; private set; }
} // class CarPeriod
// ----------------------------------------------------------------------
[Sample( "DaysTrendData" )]
public void DaysTrendData()
{
  // periods
  ITimePeriodCollection carPeriods = new TimePeriodCollection();
  carPeriods.Add( new CarPeriod( 1, new DateTime( 2013, 1, 1 ), new DateTime( 2013, 1, 1 ) ) );
  carPeriods.Add( new CarPeriod( 2, new DateTime( 2013, 1, 2 ), new DateTime( 2013, 1, 2 ) ) );
  carPeriods.Add( new CarPeriod( 3, new DateTime( 2013, 1, 2 ), new DateTime( 2013, 1, 3 ) ) );
  carPeriods.Add( new CarPeriod( 4, new DateTime( 2013, 1, 3 ), new DateTime( 2013, 1, 3 ) ) );
  carPeriods.Add( new CarPeriod( 5, new DateTime( 2013, 1, 3 ), new DateTime( 2013, 1, 5 ) ) );
  carPeriods.Add( new CarPeriod( 6, new DateTime( 2013, 1, 4 ), new DateTime( 2013, 1, 5 ) ) );
  Days testDays = new Days( new DateTime( 2013, 1, 1 ), 5 );
  foreach ( Day testDay in testDays.GetDays() )
  {
    Console.Write( "Day: " + testDay + ": " );
    foreach ( CarPeriod carPeriod in carPeriods )
    {
      if ( carPeriod.IntersectsWith( testDay ) )
      {
        Console.Write( carPeriod.Id + " " );
      }
    }
    Console.WriteLine();
  }
} // DaysTrendData