LINQ如何按日期分组日期和月份和年份

问题描述:

我创建了一种使用日期(日,月,年)对数据进行分组的方法。LINQ如何按日期分组日期和月份和年份

这是我的代码:

private IEnumerable<StatsticsVm> GetStatsticsPerDay(StatsticsQueryModel sqm) 
{ 

    var messages = GetMessagesByDateAndIU(sqm); 

    IEnumerable<StatsticsVm> messagesCountPerDay = 

     from year in Enumerable.Range(sqm.From.Year, sqm.To.Year - sqm.From.Year + 1) 
     from month in Enumerable.Range(1, 12) 
     from day in Enumerable.Range(1, 31) 
     let key = new { Year = year, Month = month, Day = day } 
     join message in messages on key 
     equals new 
     { 
      message.ObservationDateTime.Year, 
      message.ObservationDateTime.Month, 
      message.ObservationDateTime.Day 
     } into g 
     select new StatsticsVm() 
     { 
      Label = key.Day + "/" + key.Month + "/" + key.Year, 
      MessagesCount = g.Count() 
     }; 

    return messagesCountPerDay; 

} 

我的问题是:这种方法有一个bug,该bug是结果总是包含12个月,31天我想要的结果是一样的过滤器。

例如,如果我只想从第1天到第15天的数据,我总是从第1天到第31天获得小组。

注意:即使一天有0条消息,我也希望包含在我的过滤器中的所有日子。这已经在这个方法中完成了。

+0

你说要包括所有的日子,那么为什么有所有的月份和日期的问题吗? “我希望结果与过滤器一样”是什么意思? –

+0

我的意思是我只想要(几年,几个月,几天),即使这些日子里没有消息。并且这里的错误是即使我的过滤器是从第3个月到第12个月,结果总是从第1个月到第12个月以及从第1天到第31天。我希望我现在说清楚。 –

+0

从一天到十三或三十一?这有点不清楚,你应该按照最小和最大月份的方法分最小和最大月份 – Tinwor

好吧,我想我终于得到了你。

您的问题与您尝试创建DateTime范围的方式有关。

正确的方法是这样的:

Enumerable.Range(0, 1 + sqm.To.Subtract(sqm.From).Days) 
      .Select(offset => sqm.From.AddDays(offset)) 

这会给你下面的代码:

private IEnumerable<StatsticsVm> GetStatsticsPerDay(StatsticsQueryModel sqm) 
{ 

    var messages = GetMessagesByDateAndIU(sqm); 
    var dateRange = Enumerable.Range(0, 1 + sqm.To.Subtract(sqm.From).Days) 
           .Select(offset => sqm.From.AddDays(offset)); 

    IEnumerable<StatsticsVm> messagesCountPerDay = 
     from date in dateRange 
     join message in messages on date 
     equals message.ObservationDateTime into g 
     select new StatsticsVm() 
     { 
      Label = date.Day + "/" + date.Month + "/" + date.Year, 
      MessagesCount = g.Count() 
     }; 

    return messagesCountPerDay; 

} 

至于我可以看到你正在试图做的是采取邮件在日期范围内,按日期分组并按每个日期计数。

from messages in message 
where (messages .ObservationDateTime < sqm.To) 
      && (messages .ObservationDateTime > sqm.From)) 
group orders by EntityFunctions.TruncateTime(m.ObservationDateTime) 
      into dateMessages 
select new StatsticsVm() 
    { 
     Label = dateMessages.key.Day + "/" + dateMessages.key.Month + "/" + dateMessages.key.Year, 
     MessagesCount = dateMessages.Count() 
    }; 
+0

但如果是没有消息的0的日期,我想它也是在0计数的结果。 –

+0

我错过了那一点:) – Frogger

我认为这会为你工作:

private IEnumerable<StatsticsVm> GetStatsticsPerDay(StatsticsQueryModel sqm) 
{ 
    var messages = GetMessagesByDateAndIU(sqm); 

    var f = new DateTime(sqm.From.Year, 1, 1); 
    var t = new DateTime(sqm.To.Year + 1, 1, 1); 

    var lookup = messages.ToLookup(x => x.ObservationDateTime.Date); 

    IEnumerable<StatsticsVm> messagesCountPerDay = 
     from n in Enumerable.Range(0, t.Subtract(f).Days) 
     let day = f.AddDays(n) 
     select new StatsticsVm() 
     { 
      Label = day.ToString(@"d/m/y"), 
      MessagesCount = lookup[day].Count() 
     }; 

    return messagesCountPerDay; 
}