I have a snapshot table in my database that holds historical data of appointment availability.
I'm trying to write a LINQ query to get the total number of AvailableSlots within a given date range from the latest snapshot.
Here is what my table looks like:
So with this given data, I'd want my LINQ query to return the sum of AvailableSlots within the date range of 2018-01-01 - 2018-01-02 and with the latest SnapShotTime. So, I'd expect the query to return 4.
Here is what I have so far.
var test = db.snapshots
.GroupBy(g =>
g.AppointmentTime >= startDate &&
g.AppointmentTime <= endDate
).Select(s => s.OrderByDesending(x => x.SnapShotTime).FirstOrDefault();
However, I'm not sure how to put the Sum of available slots into this LINQ query. Any help on writing this query would be appreciated!
i dont see exactly the query that you wrote do, but based on your explanation i think sth like this might have work
var query=db.snapshots
.Where(x=>x.AppointmentTime >= startDate &&
x.AppointmentTime <= endDate)
.GroupBy(x=>x.SnapShotTime)
.OrderByDesending(g=>g.Key)
.Take(1)
.Sum(x=>x.Value.AvailableSlots);
or if it seems so complicated you better first get the latest date like this
var latest=db.snapshots
.OrderByDesending(x => x.SnapShotTime)
.FirstOrDefault().SnapShotTime;
and then get your count like this
var query=db.snapshots
.Where(x=>x.AppointmentTime >= startDate &&
x.AppointmentTime <= endDate &&
x.SnapShotTime==latest)
.Sum(x=>x.AvailableSlots);
Here is what I did.
static void Main(string[] args)
{
DateTime startDate = new DateTime();
DateTime endDate = new DateTime();
List<FakeAppointments> appointmentsFromDatabase = new List<FakeAppointments>();
var appointmentsBetweenStartDateAndEndDate = appointmentsFromDatabase.Where(p => p.SnapshotTime >= startDate && p.SnapshotTime <= endDate).ToList();
int sum = appointmentsBetweenStartDateAndEndDate.Sum(p => p.AvailableSlots);
Console.ReadKey();
}
public class FakeAppointments
{
public DateTime SnapshotTime;
public int AvailableSlots;
}
Related
The following query is returning a number of daily orders. I want to create another query that will return int number of orders in one month. The problem is some months have 29days, some 30 or 31. Any help is appreciated!
public int GetNewDailyOrders()
{
return _DbContext.Carts.Where(x => x.Created >= DateTime.UtcNow.AddDays(-1)).Count();
}
public int GetMonthlyOrders(int month, int year)
{
return _DbContext.Carts.Count(x => x.Created.Year == year && x.Created.Month == month);
}
may be, you should consider support different timezones, summertime or not, something like this as well
My chief complaint with Nobody's answer is that it manipulates table data, which generally kills the db's ability to use indexes
Consider instead working out the date range and querying it instead:
var n = DateTime.Now;
var f = new DateTime(n.Year, n.Month, 1);
var t = new DateTime(n.Year, n.Month + 1, 1);
_dbContext.Carts.Count(c => c.CreatedDate >= f && c.CreatedDate < t);
I have a movie rental application. The company would enter the movie rent date and movie rent end date. Dates can overlap (as you can have many customers). The data in the db is stored as
RecordID FromRentDate ToRentDate
1 2016-10-06 18:00:00.000 2016-10-06 20:00:00.000
2 2015-10-06 18:00:00.000 2015-10-06 20:00:00.000
3 2015-09-29 16:00:00.000 2015-09-30 17:00:00.000
4 2015-09-11 00:00:00.000 2015-09-11 00:00:00.000
5 2015-09-09 10:00:00.000 2015-09-09 14:30:00.000
When the user selects a date (using standard .Net controls) the following code is called
IEnumerable<Event> LiveDates = DataContext.Events.Where(d => d.StartDate.Value >= DateTime.Now);
IEnumerable<DateTime> AllLiveDates = null;
if (LiveDates != null && LiveDates.Count() > 0)
{
DateTime FromRentDate = LiveDates.Where(f => f.StartDate.HasValue).Min(f => f.StartDate).Value;
DateTime ToRentDate = LiveDates.Where(t => t.EndDate.HasValue).Max(f => f.EndDate).Value;
AllLiveDates = Enumerable.Range(0, int.MaxValue)
.Select(x => FromRentDate.Date.AddDays(x))
.TakeWhile(x => x <= ToRentDate.Date)
.Where(x => DataContext.Events.Any(c => x >= c.StartDate && x <= c.EndDate));
}
return AllLiveDates.ToList();
What i would like to happen is when a user selects a date, it gets all the dates from the selected date, to the end date including any inclusive dates where the movie is also out so using the above data, if i select todays date I should get all records back and the dates should be listed as:
2015-09-09
2015-09-11
2015-09-29
2015-09-30
2015-10-06 .... etc
Notice how 2015-09-29, 2015-09-30 are included but 2015-09-30 is not a start date. This is because the length of this movie rental is for 2 days (29 and 30 September).
The problem i am experiencing with the above code is that it only returns 1 date. Debugging it it seems to go into AllLiveDates code and something is removing the other dates but not sure what?
You could try something like this
var dateList = new List<DateTime>();
foreach (var ld in LiveDates)
{
for (var dt = ld.StartDate.Date; dt <= ld.EndDate.Date; dt = dt.AddDays(1))
{
dateList.Add(dt);
}
}
dateList = dateList.Distinct().ToList();
dateList = dateList.Sort((a, b) => a.CompareTo(b));
The issue appears to be that you are comparing a date value with a date and time.
Take for example the date 2015-09-09. When you compare that to the DateTime values in your table you should get zero matches, because the DateTime value 2015-09-09 00:00:00.0000 does not lie between the start and end DateTime values of any of your data points.
You will need to strip the time portions of your data points to get the comparison to work the way you want. Fortunately LINQ to SQL supports the .Date property of DateTime values, so this should work:
Try this:
AllLiveDates = Enumerable.Range(0, int.MaxValue)
.Select(x => FromRentDate.Date.AddDays(x))
.TakeWhile(x => x <= ToRentDate.Date)
.Where(x => DataContext.Events.Any(c => x >= c.StartDate.Value.Date && x <= c.EndDate.Value.Date));
Just don't look at the generated SQL... it's not pretty.
I have a problem; actually I am having workingHours in my database table in the format HH.mm and I want to sum all the working hours using LINQ can any 1 please tell how to do this.
In totalWeekHours I have all the working hours and I have replace HH.mm format in HH:mm but I don't know how to parse it in timespan and then Sum() using Linq.
please help.
var totalWeekHours = (from twh in db.MytimeMaster
where ((twh.date >= lstsun && twh.date <= tilldate)
&& (twh.agentID == agentid))
select twh.totalworkinghours).ToList();
if (totalWeekHours.Count > 0)
{
List cnvrtToTimespanlist = new List();
foreach(var list in totalWeekHours)
{
cnvrtToTimespanlist.Add(list.ToString().Replace('.', ':'));
}
}
You can use Aggregate method.
var sum = (from twh in db.MytimeMaster
where ((twh.date >= lstsun && twh.date <= tilldate) && (twh.agentID == agentid))
select twh.totalworkinghours).Aggregate(TimeSpan.FromMinutes(0), (total, next) => total + next);
p.s. assume used TimeSpan for time intervals.
How to compare date without time in mongodb C# driver?
I try to use this code, bot it don't work.
MongoCursor<Log> query = _logCollection.FindAs<Log>(
Query.And(Query.EQ("Date.getDate()", date.Day),
Query.EQ("Date.getMonth()", date.Month),
Query.EQ("Date.getYear()", date.Year)));
Do you have any ideas?
Query for range of dates, which include your date:
var beginDate = date.Date; // e.g. 7/24/2013 00:00:00
var endDate = beginDate.AddDays(1); // e.g. 7/25/2013 00:00:00
var query = Query.And(Query<Log>.GTE(l => l.Date, beginDate), // including
Query<Log>.LT(l => l.Date, endDate)); // not including
var result = _logCollection.FindAs<Log>(query);
Same with LINQ (MongoDB.Driver.Linq namespace):
var result = from l in _logCollection.AsQueryable()
where l.Date >= beginDate && l.Date < endDate
select l;
I´ve come to a total stop with my program and im in need of some help.
I got an xml file with customer billings and billing dates. This file has about 4000 billing dates. What i want is to sort them so the once that is in a range of a period date of 2010-04-01 - 2011-03-31 adds to a table column named period1. And the other dates goes to period2 that is 2011-04-01 - 2012-03-31.
Ive been testing and testing this solution in diffrent ways but it wont work. Im adding all the dats to a list named dates. And trying:
if (dates.All(date => date >= startDatePeriod1 && date <= stopDatePeriod1))
{
adapterBonus.InsertPeriod1Query(// insert to database));
}
else if (dates.All(date => date >= startDatePeriod2 && date >= stopDatePeriod2))
{
adapterBonus.InsertPeriod2Query(// insert to database));
}
startDatePeriod1 = 2010-04-01
stopDatePeriiod1 = 2011-03-31
and so on
The Enumerable.All extension method returns true if every element in the sequence verifies the condition. If dates contains dates in both periods, none of the ifs will run, because both calls to Enumerable.All will return false.
I'm not sure what you mean by "adds to a table column named period1", but if you mean to count all the dates in each period, use Enumerable.Count:
int period1Count = dates.Count(date => date >= startDatePeriod1 && date <= stopDatePeriod1);
int period2Count = dates.Count(date => date >= startDatePeriod2 && date <= stopDatePeriod2);
adapterBonus.InsertPeriod1Query(period1Count);
adapterBonus.InsertPeriod2Query(period2Count);
What you are doing, is the following:
Check whether ALL dates are in period one. If so, insert them into period 1 in the database. If not, check whether ALL dates are in period two and insert them into period 2 in the database.
You want to do the following:
foreach (var period1Date in dates.Where(date => date >= startDatePeriod1 &&
date <= stopDatePeriod1))
{
adapterBonus.InsertPeriod1Query(// insert period1Date to database));
}
foreach (var period2Date in dates.Where(date => date >= startDatePeriod2 &&
date <= stopDatePeriod2))
{
adapterBonus.InsertPeriod2Query(// insert period2Date to database));
}
BTW: I fixed an error in your second condition. It should be date <= stopDatePeriod2 instead of date >= stopDatePeriod2!
All return a boolean specifying whether all elements satisfy a condition. What you need is a Where() to extract those you need.
Something like:
adapterBonus.InsertPeriod1Query(dates.Where(date => date >= startDatePeriod1 && date <= stopDatePeriod1));
adapterBonus.InsertPeriod2Query(dates.Where(date => date >= startDatePeriod2 && date <= stopDatePeriod2));
Try this:
var period1Dates = dates.Where(date => date >= startDatePeriod1 && date <= stopDatePeriod1);
var period2Dates = dates.Where(date => date >= startDatePeriod2 && date >= stopDatePeriod2);
foreach(var date in period1Dates)
{ adapterBonus.InsertPeriod1Query(// insert to database)); }
etc.
easiest way to do this is doing a
startDatePeriod1 = 2010-04-01;
stopDatePeriod1 = 2011-03-01;
startDatePeriod2 = 2011-04-01;
stopDatePeriod2 = 2012-03-01;
foreach(DateTime d in dates) {
if (d => startDatePeriod1 && d <= startDatePeriod1) {
adapterBonus.InsertPeriod1Query(// insert to database));
} else if(d => startDatePeriod2 && d <= stopDatePeriod2) {
adapterBonus.InsertPeriod2Query(// insert to database));
}
}
seems like you just need a simple query for each bonus period, something like ...
var period1Dates = date.Where(date => date >= startDate1 && date <= stopDate1);
var period2Dates = date.Where(date => date >= startDate2 && date <= stopDate2);
adapterBonus.InsertPeriod1(period1Dates);
adapterBonus.InsertPeriod2(period2Dates);
As Daniel says, you're checking if all the dates are within each period, which it sound like will never be true, so nothing will be happening.