Reputation: 16887
I want to be able to get sales from the last 12 months, grouped by month. Here's what I have so far:
Class Definition:
public DateTime DateSold { get; set; }
public int Month { get; set; }
public int USDNumberItemsSold { get; set; }
public int GBPNumberItemsSold { get; set; }
public int EURNumberItemsSold { get; set; }
public int TotalNumberItemsSold { get { return USDNumberItemsSold + GBPNumberItemsSold + EURNumberItemsSold; } }
public decimal USDRevenueTotal { get; set; }
public decimal GBPRevenueTotal { get; set; }
public decimal EURRevenueTotal { get; set; }
public decimal OverallEarnings { get { return USDRevenueTotal + GBPRevenueTotal + EURRevenueTotal; } }
My Linq query is as follows:
List<MonthlySales> monthlySales = (from sale in Sales
orderby sale.DateSold descending
group sale by sale.DateSold.Month into ds
select new MonthlySales
{
DateSold = ds.Key,
USDNumberItemsSold = ds.Where(it => it.USDCut.HasValue).Where(it => it.USDCut != 0).Count(),
GBPNumberItemsSold = ds.Where(it => it.GBPrCut.HasValue).Where(it => it.GBPCut != 0).Count(),
EURNumberItemsSold = ds.Where(it => it.EURCut.HasValue).Where(it => it.EURCut != 0).Count(),
USDRevenueTotal = PerformCurrencyConversion(ds.Sum(it => it.USDCut.HasValue ? it.USDCut.Value : 0), 0M, 0M, reportRequest.BaseCurrency, endDate),
GBPRevenueTotal = PerformCurrencyConversion(0M, ds.Sum(it => it.GBPCut.HasValue ? it.GBPCut.Value : 0), 0M, reportRequest.BaseCurrency, endDate),
EURRevenueTotal = PerformCurrencyConversion(0M, 0M, ds.Sum(it => it.EURCut.HasValue ? it.EURCut.Value : 0), reportRequest.BaseCurrency, endDate),
}).Take(12).ToList();
I get the following error with this:
Cannot implicitly convert type 'int' to 'System.DateTime'
because obviously DateTime.Now.Month is an int.
I tried using the following:
Month = ds.Key
Where 'Month' is an int. This was okay but for display purposes I don't have the year or things like that.
Can anyone offer any advice?
Thanks.
Upvotes: 0
Views: 4689
Reputation: 4063
I would suggest introducing a new type to represent YearMonth
if that's what you need (see my question in comments).
BTW: If you are grouping by month only, then you can have problems in case when you get overlapping data, e.g. the data set contains data for 201101
and 201201
- both would be grouped together. When you do the grouping by yearMonth this should not be an issue.
The new type would be pretty basic (could be a struct):
public class YearMonthSold
{
public int Year {get; set;}
public int Month {get; set;}
}
MonthlySales would get this property:
public YearMonthSold DateSold { get; set; }
And the LINQ query would need updated to make use of it:
List<MonthlySales> monthlySales = (from sale in Sales
orderby sale.DateSold descending
group sale by new {Year = sale.DateSold.Year, Month = sale.DateSold.Month} into ds
select new MonthlySales
{
DateSold = new YearMonthSold {Year = ds.Key.Year, Month = ds.Key.Month},
(...)
})
.Take(12)
.ToList();
EDIT: Or as suggested by SPFiredrake:
List<MonthlySales> monthlySales = (from sale in Sales
orderby sale.DateSold descending
group sale by new YearMonthSold {Year = sale.DateSold.Year, Month = sale.DateSold.Month} into ds
select new MonthlySales
{
DateSold = ds.Key,
(...)
})
.Take(12)
.ToList();
I don't know the code for the Sale
object, but it doesn't seem that it should be affected by this change in any way.
Upvotes: 1
Reputation: 6484
Why don't you group by DateTime, so you will be able to set « DateSold » with « ds.Key ».
And if you want the Month of the DateTime store in the Key, you can just « ds.Key.Month ».
Upvotes: 1
Reputation: 3892
What I would recommend would be to set the key to the first of the month in question, that way you also have the year information present (which you will need since you want the last 12 months).
...
group sale by sale.DateSold.Date.AddDays(-(sale.DateSold.Day - 1)) into ds
orderby ds.Key descending
...
You also want to order by after the grouping instead of before, since grouping uses hash of keys instead of values, so you might not get the same ordering.
Upvotes: 1