LINQ Query for GroupBy and Max in a Single Query - c#

I have the following LINQ query but i want to modify it that I want to group by staffId and pick only those records whose ObservationDate is Max for each staffId.
from ob in db.TDTObservations.OfType<TDTSpeedObservation>()
select new
{
Id = ob.ID,
AcademicYearId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().AcademicYearID,
observationDate = ob.ObservationDate,
schoolId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().SchoolID,
staffId=ob.Teachers.FirstOrDefault().ID
};

var observations =
from ob in db.TDTObservations.OfType<TDTSpeedObservation>()
select new {
Id = ob.ID,
AcademicYearId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().AcademicYearID,
observationDate = ob.ObservationDate,
schoolId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().SchoolID,
staffId=ob.Teachers.FirstOrDefault().ID
};
var result = from o in observations
group o by o.staffId into g
select g.OrderByDescending(x => x.observationDate).First();

what about this: hereby you first group your entries (Teachers) by their ID together and then from each group (grp) you pick that one with the latest ObservationDate
var observations = from d in db.TDTObservations.OfType<TDTSpeedObservation>()
group d by d.Teachers.FirstOrDefault().ID into grp
select grp.OrderByDescending(g => g.ObservationDate).FirstOrDefault();

Related

LINQ Query with GroupBy, MAX and Count

What could be the LINQ query for this SQL?
SELECT PartId, BSId,
COUNT(PartId), MAX(EffectiveDateUtc)
FROM PartCostConfig (NOLOCK)
GROUP BY PartId, BSId
HAVING COUNT(PartId) > 1
I am actually grouping by two columns and trying to retrieve max EffectiveDateUtc for each part.
This is what I could write. Stuck up on pulling the top record based on the date.
Also not sure, if this is a optimal one.
//Get all the parts which have more than ONE active record with the pat
//effective date and for the same BSId
var filters = (from p in configs
?.GroupBy(w => new
{
w.PartId,
w.BSId
})
?.Select(g => new
{
PartId = g.Key.PartId,
BSId = g.Key.BSId,
Count = g.Count()
})
?.Where(y => y.Count > 1)
select p)
?.Distinct()?.ToList();
var filteredData = (from p in configs
join f in filters on p.PartId equals f.PartId
select new Config
{
Id = p.Id,
PartId = p.PartId,
BSId = p.BSId,
//EffectiveDateUtc = MAX(??)
}).OrderByDescending(x => x.EffectiveDateUtc).GroupBy(g => new { g.PartId, g.BSId }).ToList();
NOTE: I need the top record (based on date) for each part. Was trying to see if I can avoid for loop.
The equivalent query would be:
var query =
from p in db.PartCostConfig
group p by new { p.PartId, p.BSId } into g
let count = g.Count()
where count > 1
select new
{
g.Key.PartId,
g.Key.BSId,
Count = count,
EffectiveDate = g.Max(x => x.EffectiveDateUtc),
};
If I understand well, you are trying to achieve something like this:
var query=configs.GroupBy(w => new{ w.PartId, w.BSId})
.Where(g=>g.Count()>1)
.Select(g=>new
{
g.Key.PartId,
g.Key.BSId,
Count = g.Count(),
EffectiveDate = g.Max(x => x.EffectiveDateUtc)
});

Select Min and Max LINQ

select description, min(date), max(date), sum(value1), sum(value2) from table
where description = 'Axxx' and filter = 'L'
group by description
How to perform this query using Linq / C#?
Not tested, but the following should work:
table
.Where(x=>x.description=="Axxx" && x.filter=="L")
.GroupBy(x=>x.description)
.Select(x=>new {
description=x.Key,
mindate=x.Min(z=>z.date),
maxdate=x.Max(z=>z.date),
sumvalue1=x.Sum(z=>z.value1),
sumvalue2=x.Sum(z=>z.value2)
});
something like this should work. not tested
var q = from b in table
group b by b.Owner into g
where description = 'Axxx'
select new
{
description = g.description ,
date = g.min(),
date = g.max(),
value1= g.Sum(item => item.value1),
value2= g.Sum(item => item.value2),
};
That should work
var q = from s in db.table
where description = 'Axxx' and filter = 'L'
group s by s.description into g
select new {YourDescription = g.description, MaxDate = g.Max(s => s.date) }
That answer may help, too .. here

How can I order the output of my long LINQ query by a double and then a string?

I have the following LINQ query:
summaries = from m in _master
join d in _detail on pk + m.RowKey equals d.PartitionKey into outer
from d in outer.DefaultIfEmpty()
select new
{
Position = m.Position,
Title = m.Title,
Detail = ((d == null) ? 0 : 1),
PartitionKey = m.PartitionKey,
RowKey = m.RowKey,
Modified = m.Modified,
ModifiedBy = m.ModifiedBy
} into split
group split by split.Title into g
select new AdminSummary
{
Position = g.Last().Position,
Title = g.Key,
DetailCount = g.Sum(s => s.Detail),
PartitionKey = g.Last().PartitionKey,
RowKey = g.Last().RowKey,
Modified = g.Last().Modified,
ModifiedBy = g.Last().ModifiedBy
};
The query works well but now I would like to do an order by on Position (double) followed by Title (string).
Can someone advise how I can do this?
Can someone tell me how to do the order by?
It's pretty easy:
summaries = summaries.OrderBy(item =>item.Position).ThenBy(item =>item.Title);
Also you can use OrderByDescending() and ThenByDescending() if you need them in descending order
Do this after your above query.
summaries = from s in summaries
orderby s.Position,s.Title
select s

How to distinct select and group with castle active records?

How can I execute the following SQL-Query using LINQ or HQL?
SELECT `year`, `month`, COUNT(code_id)
FROM (SELECT DISTINCT request_codes_id AS code_id,
YEAR(requested) AS `year`, MONTH(requested) AS `month` FROM requests) r
GROUP BY `year`, `month`
ORDER BY `year`, `month`;
I tried the following:
var items = from r in TestaccountRequest.Queryable
group r by r.RequestCodeId into g
select g.First();
var grouped = from r in items
group r by r.Requested.ToString("yyyyMM") into y
select new { Year = y.First().Requested.Year, Month = y.First().Requested.Month, Count = y.Count() };
which threw a System.String ToString(System.String) NotSupportedException.
UPDATE:
The g.First() in the first LINQ-Query seems to cause the problem, because if I only run the first one I get a Code supposed to be unreachable-Exception, but if I remove the .First() it "works", but does not return what I need.
Group by an anonymous type instead:
var grouped = from r in items
group r by new { Year = r.Requested.Year,
Month = r.Requested.Month } into g
select new { g.Key.Year, g.Key.Month, Count = g.Count() };
I kinda solved it using the following:
var items = from r in TestaccountRequest.Queryable
group r by r.RequestCodeId into g
select g.ElementAt(0);
var grouped = from r in items.ToList()
group r by new { Year = r.Requested.Year,
Month = r.Requested.Month } into g
select new { g.Key.Year, g.Key.Month, Count = g.Count() };
but I gues thats not the best solution as all objects are getting fetched from the DB, but at least it is working for now, but please provide a better solution if available.
EDIT:
I now solved it using HQL:
HqlBasedQuery query = new HqlBasedQuery(typeof(ActivationCodeTestaccountRequestRecord),
"SELECT DISTINCT r.ActivationCodeId, YEAR(r.Requested), MONTH(r.Requested) " +
"FROM ActivationCodeTestaccountRequestRecord r");
var items = from object[] row in (ArrayList)ActiveRecordMediator.ExecuteQuery(query)
group row by new { Year = row[1], Month =row[2] } into g2
select new { Year = g2.Key.Year, Month = g2.Key.Month, Count = g2.Count() };

How can I filter results of one LINQ query based on another?

Given the following:
DP_DatabaseTableAdapters.EmployeeTableAdapter employeetableAdapter = new DP_DatabaseTableAdapters.EmployeeTableAdapter();
DP_Database.EmployeeDataTable employeeTable = employeetableAdapter.GetData();
var leadEmployees = from e in employeeTable
where e.IsLead == true
select e;
DP_DatabaseTableAdapters.LaborTicketTableAdapter tableAdapter = new DP_DatabaseTableAdapters.LaborTicketTableAdapter();
DP_Database.LaborTicketDataTable table = tableAdapter.GetDataByDate(date.ToString("MM/dd/yyyy"));
var totHours = from l in table
join e in leadEmployees on l.EmployeeID equals e.EmployeeID
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};
Total hours correctly filters the results based on the leadEmployee's list of people who have the IsLead bit set to true.
I would like to know how to do this with a where clause, I have attempd to use leadEmployees.Contanis but it wants a whole EmployeeRow...
How can I add what looks to be part of an IN clause to a where filter to replace the join?
var totHours = from l in table
where ??????
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};
The contains will only want a whole EmployeeRow if you are selecting whole employee roles. You can either:
leadEmployees.Select(e => e.id).contains
OR
leadEmployees.Count(e => e.id == l.id) > 0
Both will work. (Excuse slightly rushed lack of consideration for syntax accuracies).
This should work:
var leadEmployees = from e in employeeTable
where e.IsLead == true
select e.EmployeeID;
var totHours = from l in table
where leadEmployees.Contains(l.EmployeeID)
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};

Categories

Resources