【问题标题】:Creating trend data from data that has start and end date spaning days从具有跨天开始和结束日期的数据创建趋势数据
【发布时间】:2013-09-17 20:48:51
【问题描述】:

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

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

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

我想知道过去 30 天内每天有多少辆车。所以可以在趋势图中使用的数据。

说明

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

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

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

如果我在数据库中说这个数据:

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 服务上太昂贵了。

建议?

【问题讨论】:

  • 因为是域,一天可以700个条目,没关系,我把细节缩短了,所以只有需要的数据。
  • 我的错,我会更新:)
  • 我检查了 2013-01-04 和 2013-01-05 似乎很好:条目 5 从 2013-01-03 到 2013-01-05 持续 3 天:2013-01-03 2013-01-04 2013-01-05 条目 6 从 2013-01-04 到 2013-01-05,这使得 2 天:2013-01-04 2013-01-05 所以 2013-01-04 变为 2:条目: 5 和 6。所以 2013-01-05 变为 2:条目:5 和 6。

标签: c# linq nhibernate fluent-nhibernate


【解决方案1】:

可能是这样的:

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();

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

【讨论】:

  • 这假设我有一个DateCreated 列,我没有那个。你理解我的问题。我想知道,每一天,那天有多少条目。所以我可以创建一个趋势图。
  • 我仍然没有DateCreated 专栏,即使我有它,也无助于我的问题。如果我有的话,如果我按此列分组,它将给我错误的趋势。如果我这样运行它,我可能会按 StartDate 分组并得到几天的错误结果。
  • 我用一个故事更新了这个问题,如果这样更清楚的话。
  • 我有一个关于这个的问题,如果我选择 6 个月,那在 360 where 子句的加号中不会给我一些仅适用于日期的内容吗?还是您的意思是在内存中执行此操作?
  • 我们只在短时间内(15-30 天)使用它,没有问题,但对于较长的时间,您必须测试它是如何工作的。
【解决方案2】:

您可以使用Time Period Library for .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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-08
    • 2023-03-27
    • 2018-12-02
    • 2019-08-24
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多