LINQ: Group by month and year within a datetime field
I have a table with a datetime field. I want to retrieve a result set grouped by the month/year combination and the number of records that appear within that month/year. How can this be done in LINQ?
The closest I've been able to figure out is in TSQL:
select substring(mo,charindex(mo,'/'),50) from (
select mo=convert(varchar(2),month(created)) + '/' + convert(varchar(4), year(created))
,qty=count(convert(varchar(2),month(created)) + '/' + convert(varchar(4), year(created)))
from posts
group by convert(varchar(2),month(created)) + '/' + convert(varchar(4), year(created))
) a
order by substring(mo,charindex(mo,'/')+1,50)
But I wouldn't say that works...
Solution 1:
var grouped = from p in posts
group p by new { month = p.Create.Month,year= p.Create.Year } into d
select new { dt = string.Format("{0}/{1}",d.Key.month,d.Key.year), count = d.Count() };
Here's the list of DateTime functions available in LINQ. For this to work you'll also need to understand multi-column grouping
ordered descending
var grouped = (from p in posts
group p by new { month = p.Create.Month,year= p.Create.Year } into d
select new { dt = string.Format("{0}/{1}",d.Key.month,d.Key.year), count = d.Count()}).OrderByDescending (g => g.dt);
Solution 2:
This is for those who are trying to accomplish the same but using lambda expressions.
Assuming that you already have a collection of entities and each entity has OrderDate as one of its properties.
yourCollection
// This will return the list with the most recent date first.
.OrderByDescending(x => x.OrderDate)
.GroupBy(x => new {x.OrderDate.Year, x.OrderDate.Month})
// Bonus: You can use this on a drop down
.Select(x => new SelectListItem
{
Value = string.Format("{0}|{1}", x.Key.Year, x.Key.Month),
Text = string.Format("{0}/{1} (Count: {2})", x.Key.Year, x.Key.Month, x.Count())
})
.ToList();
If you do not need the collection of SelectListItem then just replace the select with this one:
.Select(x => string.Format("{0}/{1} (Count: {2})", x.Key.Year, x.Key.Month, x.Count()))
Solution 3:
you could also do it this way
from o in yg
group o by o.OrderDate.ToString("MMM yyyy") into mg
select new { Month = mg.Key, Orders = mg }
Your result will be
{Jan 2014, 25} {Feb 2015, 15} etc...
Solution 4:
This Site has an example that should fill your need.
This is the basic syntax:
from o in yg
group o by o.OrderDate.Month into mg
select new { Month = mg.Key, Orders = mg }