I'm trying to figure out how to count the number of Mondays, Tuesdays etc in a table using Linq and C#
Here is my sample data:
Status StatusDate
DELIVRD 2015-04-16 11:57:47.000
DELIVRD 2015-04-16 13:02:57.000
I know I need to use Group by to group the same Mondays, Tuesdays etc as 1.
My attempt:
var mondays = rad.SMSSentItems
.Where(x => (x.StatusDate.Value.DayOfWeek == DayOfWeek.Monday)
&& (x.Status == "DELIVRD"))
.ToList()
.Count;
You need to filter by the desired Status (DELIVRD) then group them by DayOfWeek of the status date
var weekDays = rad.SMSSentItems
.Where(x => x.Status == "DELIVRD")
.AsEnumerable()
.GroupBy(x => x.StatusDate.Value.DayOfWeek)
.Select(g => {
//Total items sent on this day of the week
var totalItemCount = g.Count();
//Total number if this distinct day of the week
var totalNumberOfDays = g.Select(x => x.StatusDate.Value.Date).Distinct().Count();
return new {
DayOfWeek = g.Key,
TotalItemCount = totalItemCount,
TotalNumberOfDays = totalNumberOfDays,
AverageItemPerDay = totalItemCount / totalNumberOfDays
};
})
.ToList();
Related
I want something really simple, i want from a list of records to find the ones of a specific date (records can have the same date more than once) and with a specific value,
and count how many of those values exist. So far i'm using this but im not sure if it is the best approach
Here is Records
public class Records
{
public DateTime Date { get; set; }
public int Record { get; set; }
}
and here is the code
List<Records> records = GetRecords();
var distinctDates = records.Select(x => x.Date).Distinct().ToList();
for (int i = 0; i < distinctDates.Count(); i++)
{
statistics.Rows.Add(new object[] { distinctDates[i].ToString("MM/dd/yyyy HH:mm"),
records.Select(x => x).Where(d => d.Date == distinctDates[i]).Count(x => x.Record == -1).ToString()});
}
I want to know the sum of the appearance of a specific Date and a specific value in Record
So if the database has these values:
11/11/1980, 3
11/11/1980, 3
12/11/1980, 2
I want to get as a result 2 when i will seek for the count of the conditions 11/11/1980 and 3
var result = records.GroupBy(x => x.Date)
.Select(x => new { Date = x.Key, Count = x.Count() });
is what you want
result will now have a list of dates and count.
if you want a specific value then like this:
var result = records.Where(x => x.Record == -1).
.GroupBy(x => x.Date)
.Select(x => new { Date = x.Key, Count = x.Count() });
To group by the date and not the date time use the date property of the object in the GroupBy statement
.GroupBy(x => x.Date.Date)
What you want is a couting of all dates. GroupBy() allows you to distinctly select all dates. Then you can Count() all grouped records with some conditions as you want.
records.GroupBy(x => x.Date).Select(x => new
{
Date = x.Key,
Count = x.Count(y => y.Record == -1)
}) // This should give you all distinct dates with count
So given a DateTime date and an int recordValue, you want to count all Records from your recordCollection that have a property Date equal to date and a property Record equal to RecordValue.
How about this:
Datetime date = new DateTime(1980, 11, 11);
int recordValue = 3;
var result = recordCollection
// keep only the records with date and recordValue:
.Where(record => record.Date == date && record.Record == recordValue)
// and Count them:
.Count();
I have a Customers and an Orders database.
I need to make some statistics for the first order of all new customers and count the number of first orders from new clients by month.`
var date = new DateTime(now.Year - 1, now.Month, 1);
db.Orders
.Where(o => o.Customer.IsNew && o.OrderDate > date)
.GroupBy(o => new { o.OrderDate.Year, o.OrderDate.Month })
.Select(g => new NewCustomerStatsModel {
Month = g.Key.Month,
Year = g.Key.Year,
Count = g.Count()
})
.OrderBy(cs => cs.Year)
.ThenBy(cs => cs.Month)
.ToList();
This query provide me the number of orders for all new client but I need to get only the sum of the first order for each new Customer if the first order date is greater than the provided date.
Is it possible to do it with a query (and how) or am I forced to use AsEnumerable and do it in memory?
I need to make some statistics for the first order of all new customers
var clientFirstOrders = db.Customers.Where(c => c.IsNew)
.Select(c => new{
Customer = c,
FirstOrder = c.Orders.OrderBy(c => c.OrderDate).FirstOrDefault()
})
// might have to do (int?)FirstOrder.Id != null or something like that.
.Where(e => e.FirstOrder != null);
and count the number of first orders from new clients by month.
var clientCountByFirstOrderMonth = clientFirstOrders
.GroupBy(e => new { e.FirstOrder.OrderDate.Year, e.FirstOrder.OrderDate.Month })
.Select(g => new{g.Key.Year, g.Key.Month, Count = g.Count()});
I could find the solution.
With some appropriate index, the performances are pretty good.
It's probably not a perfect solution, but I couldn't update the entities because it's not my Library.
var date = new DateTime(now.Year - 1, now.Month, 1);
var result = db.Orders
.Where(o => o.Customer.IsNew && o.State != OrderState.Cancelled) // get all orders where the Customer is a new one.
.GroupBy(o => o.Customer.Id) // group by customer
.Select(g => g.OrderBy(o => o.OrderDate).FirstOrDefault()) // get the first order for every customer
.Where(o => o.OrderDate > date) // restrict to the given date
.GroupBy(o => new { o.OrderDate.Year, o.OrderDate.Month) }) // then group by month
.Select(g => new NewCustomerStatsModel {
Month = g.Key.Month,
Year = g.Key.Year,
Count = g.Count()
})
.OrderBy(g => g.Year)
.ThenBy(g => g.Month)
.ToList();
I'm trying to get the total average count of row instances by day of week. So over the past year, I'm trying to get the average amount of rides that happened on a monday/tuesday/wed/ect.
Here's what I have so far. That gives me the total count per day of week, but not the average count.
UnitOfWork.Query<WorkoutRecord>()
.Where(x => x.WorkoutDate > baseDate)
.GroupBy(x => SqlFunctions.DatePart("weekday", x.UploadDate))
.Select(x => new AdminDashboardWorkoutsGroupedDay()
{
DayOfWeek = (DayOfWeek)x.Key,
WorkoutCount = x.Count()
}).ToList();
If I understand you well, in the end you're trying to get one number, the average count per weekday. This requires a second grouping that reduces the data to one group:
UnitOfWork.Query<WorkoutRecord>()
.Where(x => x.WorkoutDate > baseDate)
.GroupBy(x => SqlFunctions.DatePart("weekday", x.UploadDate))
.Select(x => new AdminDashboardWorkoutsGroupedDay()
{
DayOfWeek = (DayOfWeek)x.Key,
WorkoutCount = x.Count()
})
.GroupBy(g => 0) // or g => "x", or whatever
.Select (g1 => (decimal)g1.Sum(x => x.WorkoutCount) / g1.Count())
.ToList();
Here's what worked. Thanks #Gert Arnold, you got me really close. I had to group by day and count all the workouts, then take the average of that grouping by weekday.
UnitOfWork.Query<WorkoutRecord>()
.Where(x => x.WorkoutDate > baseDate && x.TotalTicks > 600)
.GroupBy(x => EntityFunctions.TruncateTime(x.UploadDate))
.Select(x => new
{
Date = x.Key ?? DateTime.UtcNow,
TheCount = x.Count()
})
.GroupBy(x=> SqlFunctions.DatePart("weekday", x.Date))
.Select (x => new AdminDashboardWorkoutsGroupedDay()
{
WorkoutCount = (x.Average(y=>y.TheCount)),
DayOfWeek = (DayOfWeek)x.Key
})
.ToList()
It's not clear what property you want the average of, but assuming you have a property like WorkoutRecord.Duration, you should be able to get the average like:
UnitOfWork.Query<WorkoutRecord>()
.Where(x => x.WorkoutDate > baseDate)
.GroupBy(x => SqlFunctions.DatePart("weekday", x.UploadDate))
.Select(x => new AdminDashboardWorkoutsGroupedDay()
{
DayOfWeek = (DayOfWeek)x.Key,
AverageDuration = x.Average(w => w.Duration)
})
.ToList();
Here unoinColumn is return the all the date with out duplicate but i want to get the date group by month
month totalamount
7/2014 10000
8/2014 10000
enter code here var unoinDateColumn = (from agent in db.collections
where agent.Date_Time.Value.Year == thisYear
select agent.Date_Time).Union(from u in db.bank_deposit
where u.Date_Time.Value.Year == thisYear
select u.Date_Time).ToList();
You can do something like that, if I understood well.
Filter collections and deposits by given year, select date_time and amount
Union, group by month, select date in the desired format, and sum amount.
You can of course do all that in one query, but I'm not sure this will be easier to read ;)
var collections = db.Collections.Where(x => x.Date_Time.Value.Year == thisYear)
.Select(m => new {
dt = m.Date_Time.Value,
amount = m.Amount
});
var deposits = db.Collections.Where(x => x.Date_Time.Value.Year == thisYear)
.Select(m => new {
dt = m.Date_Time.Value,
amount = m.Amount
});
var result = collections.Union(deposits)
.GroupBy(m => m.dt.Month)
.Select(g => new {
date = g.First().dt.ToString("MM/yyyy"),
totalAmount = g.Sum(x => x.amount)
});
I have this block of code.
var foundAppointments = ServiceLink.FindAppointments(User, SiteSecureKey);
var MondayAppointments = foundAppointments.SelectMany(x => x.Where(y => y.StartTime.Date.DayOfWeek == DayOfWeek.Monday)).ToList();
Now I have a global list which I add each days appointments too e.g. Monday, Tuesday, Wed etc..
Then I run this:
Appointments.Add(MondayAppointments); ..........
Is there any whay I can run the Monday through Sunday appointments than having to write.
var TuesdayAppointments = foundAppointments.SelectMany(x=>x.Where(y => y.StartTime.Date.DayOfWeek == DayOfWeek.Tuesday)).ToList();
var WednesdayAppointments = foundAppointments.SelectMany(x=>x.Where(y => y.StartTime.Date.DayOfWeek == DayOfWeek.Wednesday)).ToList();
var ThursdayAppointments = foundAppointments.SelectMany(x=>x.Where(y =>y.StartTime.Date.DayOfWeek == DayOfWeek.Thursday)).ToList();
var FridayAppointments = foundAppointments.SelectMany(x=>x.Where(y => y.StartTime.Date.DayOfWeek == DayOfWeek.Friday)).ToList();
var SaturdayAppointments = foundAppointments.SelectMany(x => x.Where(y => y.StartTime.Date.DayOfWeek == DayOfWeek.Saturday)).ToList();
var SundayAppointments = foundAppointments.SelectMany(x => x.Where(y => y.StartTime.Date.DayOfWeek == DayOfWeek.Saturday)).ToList();
Appointments.Add(TuesdayAppointments);
Appointments.Add(WednesdayAppointments);
Appointments.Add(ThursdayAppointments);
Appointments.Add(FridayAppointments);
Appointments.Add(SaturdayAppointments);
Appointments.Add(SundayAppointments);
Any ideas?
You can enumerate over values from DayOfWeek enum and get appointments of each day:
var days = Enum.GetValues(typeof(DayOfWeek));
foreach (DayOfWeek dayOfWeek in days)
{
var dayAppointments = foundAppointments.SelectMany(x => x.Where(y => y.StartTime.Date.DayOfWeek == dayOfWeek)).ToList();
Appointments.Add(dayAppointments);
}
If you need Monday to be first, then sort days:
var days = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>()
.OrderBy(d => d == DayOfWeek.Sunday)
.ThenBy(d => d);
BTW why you are adding appointments day by day? Looks like you can add all at once. If you want to add appointments in order starting from Monday:
var appintmentsToAdd = foundAppointments
.SelectMany(x => x)
.OrderBy(a => a.StartTime.Date.DayOfWeek == DayOfWeek.Sunday)
.ThenBy(a => a.StartTime.Date.DayOfWeek)
.ToList();
Appointments.Add(appintmentsToAdd);
Use Enum.GetValues to get all possible DayOfWeek values:
var days = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>().ToArray();
And AddRange to add more than one element to Appointments at once:
var foundAppointments = ServiceLink.FindAppointments(User, SiteSecureKey);
Appointments.AddRange(days.Select(d => foundAppointments.SelectMany(x=>x.Where(y => y.StartTime.Date.DayOfWeek == d)).ToList());
Or just create Appointments directly from your query:
var Appointments.AddRange(days.Select(d => foundAppointments.SelectMany(x=>x.Where(y => y.StartTime.Date.DayOfWeek == d)).ToList()).ToList();
Try this:
IEnumerable<DayOfWeek> daysOfWeek = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>();
var appointmentsOnDaysOfWeek = daysOfWeek
.GroupJoin(
foundAppointments,
dayOfWeek => dayOfWeek,
appointment => appointment.StartDate.DayOfWeek,
(day, appointments) => new
{
Day = day,
Appointments = appointments.ToList()
})
.OrderBy(appointmentsOnDay => appointmentsOnDay.Day)
.Select(appointmentsOnDay => appointmentsOnDay.Appointments);
Appointments.AddRange(appointmentsOnDaysOfWeek);
Update:
I didn't pay attension to ordering by days when monday should be first. To fix it replace
.OrderBy(appointmentsOnDay => appointmentsOnDay.Day)
with
.OrderBy(appointmentsOnDay => appointmentsOnDay.Day == DayOfWeek.Sunday)
.ThenBy(appointmentsOnDay => appointmentsOnDay.Day)