如何获取此查询以获取过去12个月的每月统计数据?我不想对范围进行硬编码,我想使用当前日期DateTime.Now
并获取过去12个月的所有数据。我试图避免将日历表添加到数据库,只使用LINQ
。
有些月份可能没有任何数据,但我仍然需要0
的数量。
例如。如果我的数据包含
Date Count
12/2/2013, 4
10/1/2014, 1
11/5/2014, 6
结果应使用当前日期2014年11月9日
11/2013, 0
12/1013, 4
1/2014, 0
2/2014, 0
3/2014, 0
4/2014, 0
5/2014, 0
6/2014, 0
7/2014, 0
8/2014, 0
9/2014, 0
10/2014, 1
11/2014, 6
我无法让它发挥作用。我认为这是我使用Range
的方式,但我不确定。
TimeSpan ts = new TimeSpan(365, 0, 0, 0);
DateTime yearAgo = DateTime.Now.Subtract(ts);
var changesPerYearAndMonth =
from year in Enumerable.Range(yearAgo.Year, 1)
from month in Enumerable.Range(1, 12)
let key = new { Year = year, Month = month }
join revision in list on key
equals new { revision.LocalTimeStamp.Year,
revision.LocalTimeStamp.Month } into g
select new { GroupCriteria = key, Count = g.Count() };
我已将此链接的答案修改为起点。 Linq: group by year and month, and manage empty months
我刚发现这篇文章是同一个问题,但没有答案 Linq - group by datetime for previous 12 months - include empty months
答案 0 :(得分:3)
要过去十二个月,请使用
var now = DateTime.Now;
var months = Enumerable.Range(-12, 12)
.Select(x => new {
year = now.AddMonths(x).Year,
month = now.AddMonths(x).Month });
为了安全起见,你应该先行动,现在'到月初,以避免AddMonth
的任何月末影响。
var now = DateTime.Now;
now = now.Date.AddDays(1-now.Day);
完整示例: -
var list = new [] {
new { LocalTimeStamp = DateTime.Parse("12/2/2013"), count = 4},
new { LocalTimeStamp = DateTime.Parse("10/1/2014"), count = 1 },
new { LocalTimeStamp = DateTime.Parse("11/5/2014"), count = 6}
};
var now = DateTime.Now;
now = now.Date.AddDays(1-now.Day);
var months = Enumerable.Range(-12, 13)
.Select(x => new {
year = now.AddMonths(x).Year,
month = now.AddMonths(x).Month });
var changesPerYearAndMonth =
months.GroupJoin(list,
m => new {month = m.month, year = m.year},
revision => new { month = revision.LocalTimeStamp.Month,
year = revision.LocalTimeStamp.Year},
(p, g) => new {month = p.month, year = p.year,
count = g.Sum(a => a.count)});
foreach (var change in changesPerYearAndMonth)
{
Console.WriteLine(change.month + " " + change.year +" " + change.count);
}
答案 1 :(得分:2)
您不需要3方式加入,只需在分组前过滤数据即可。
1)查询表达式语法
// since your list item type was not posted, anyway same access as your LocalTimeStamp property
list = new List<DateTime>();
DateTime aYearAgo = DateTime.Now.AddYears(-1);
var dateslastYear = from date in list
where date > aYearAgo
group date by new { date.Year, date.Month } into g
select new { GroupCriteria = g.Key, Count = g.Count() };
2)链接
dateslastYear = list.Where (d=>d>aYearAgo)
.GroupBy (date=>new{date.Year, date.Month });
3)如果您希望按年/月对进行分组,包括不存在的条目的记录,并且还要省略那些与加入的Enumerable.Range
电话相关的年龄超过一年的对:
var thisYearPairs = from m in Enumerable.Range(1, DateTime.Now.Month)
select new { Year = DateTime.Now.Year, Month = m };
var lastYearPairs = from m in Enumerable.Range(DateTime.Now.Month, 12 - DateTime.Now.Month + 1)
select new { Year = DateTime.Now.Year - 1, Month = m };
var ymOuter = from ym in thisYearPairs.Union(lastYearPairs)
join l in list on new { ym.Year, ym.Month } equals new { l.Year, l.Month } into oj
from p in oj.DefaultIfEmpty()
select new { a = ym, b = p == null ? DateTime.MinValue : p };
var ymGroup = from ym in ymOuter
group ym by ym into g
select new { GroupCriteria = g.Key.a, Count = g.Key.b == DateTime.MinValue ? 0 : g.Count() };
答案 2 :(得分:1)
你正在考虑去年12个月的范围,但实际上你想要过去12个月。
您可以使用Enumerable.Range
和AddMonths
方法执行此操作:
var changesPerYearAndMonth =
from month in Enumerable.Range(0, 12)
let key = new { Year = DateTime.Now.AddMonths(-month).Year, Month = DateTime.Now.AddMonths(-month).Month }
join revision in list on key
equals new
{
revision.LocalTimeStamp.Year,
revision.LocalTimeStamp.Month
} into g
select new { GroupCriteria = key, Count = g.Count() };
答案 3 :(得分:0)
public int YearDiff(DateTime a, DateTime b)
{
return (int) Math.Floor((a.Year + a.Month / 100.0 + a.Day / 10000.0) - (b.Year + b.Month / 100.0 + b.Day / 10000.0));
}