Reputation: 343
I am trying to return number of records per day for a week. My code returns me only records for the day that has records, I want to return 0 if no records were inserted that day. Following is my code.
//Desired Result Sun to Sat = [0,3,5,1,0,18,0] , currently I only get [3,5,1,18] // DateTime.Now.FirstDayOfWeek() is extension method that return first day of the week. Thank you for help.
var records = logs.Where(x=>x.date> DateTime.Now.FirstDayOfWeek())
.GroupBy(x => x.date.Day)
.Select(x =>
x.Any()?x.Count():0
).ToArray();
Upvotes: 1
Views: 1009
Reputation: 26936
Using another extension method to create a range of dates:
public static IEnumerable<DateTime> Range(this DateTime startDate, int numberOfDays) => Enumerable.Range(0, numberOfDays).Select(e => startDate.AddDays(e));
You can GroupJoin
with the week of dates and create the array:
var recordgroups = logs.Where(x => x.date > DateTime.Now.FirstDayOfWeek())
.GroupBy(x => x.date.Day);
var records = DateTime.Now.FirstDayOfWeek().Range(7)
.GroupJoin(recordgroups, wd => wd.Day, lg => lg.Key, (_, lg) => lg.Any() ? lg.First().Count() : 0).ToArray();
Upvotes: 1
Reputation: 13146
You can't join with a List
and DbSet
because Linq to Entities can't translate a List
to SQL language. So, It seems that there is no option except to fill the empty days in a loop;
var records = logs
.GroupBy(x => SqlFunctions.DatePart("dw", x.date))
.Select(x =>
new WeekCounts
{
Day = x.Key,
Count = x.Count()
}).ToList();
for (int i = 0; i < 7; i++)
{
if (records.All(x => x.Day != i))
{
records.Add(new WeekCounts { Day = i, Count = 0 } );
}
}
public class WeekCounts
{
public int? Day;
public int Count;
}
Upvotes: 1
Reputation: 23866
I am not sure this solution will work, but just give it a try, simply you can do left outer join with static list, below is just snippet (pseudo code) how to do it.
List<String> weekdays = new List<String>();
weekdays.Add("Monday");
weekdays.Add("Tuesday");
...
...
...
//Left outer join to display forcibly all weekdays and join them with your log's data and continue to grouping.
var result = from w in weekdays
join l in logs into joined
from j in joined.DefaultIfEmpty()
If it did not work, please leave a comment as I've another solution for you to make it workable :)
If it did not work, check this, after returning the results, left join your static data (weekdays) with the results (records) which means you've returned only the records that their counts have data (>0) but for only those that don't have data at all, it should be coming as zero after the join.
var result = from w in weekdays
join l in records into joined
from j in joined.DefaultIfEmpty()
Upvotes: 1