I have students table and I have subjects tables I need to group students by subjects . I tried following which doesnt show s.StudentSubjects.SubjectName . How can I write group by with child table .
Students -> StudentID | Name
StudentSubjects -> SubjectID | StudentID | SubjectName
var list = from s in students
group s by s.StudentSubjects.? into g
select new StudentSubjectsCounts
{
Name = g.Key,
Count = g.Count(),
};
Sounds like you should query off of StudentSubjects instead of Student:
var list = from ss in studentSubjects
group ss by s.SubjectName into g
select new StudentSubjectsCounts
{
Name = g.Key,
Count = g.Count(),
};
Or, to start from a list of students:
var list = students.SelectMany(s => s.StudentSubjects)
.GroupBy(ss => ss.SubjectName)
.Select(g => new StudentSubjectsCounts
{
Name = g.Key,
Count = g.Count(),
});
You should be able to group by the StudentSubject object itself
var list = from s in students
group s by s.StudentSubjects into g
select new StudentSubjectsCounts
{
Name = g.Key.SubjectName,
Count = g.Count(),
};
but if you don't want to, project the name using a Select
var list = from s in students
group s by s.StudentSubjects.Select(ss => ss.SubjectName) into g
select new StudentSubjectsCounts
{
Name = g.Key,
Count = g.Count(),
};
Related
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)
});
This question already has answers here:
Group By Multiple Columns
(14 answers)
Closed 6 years ago.
Trying to group by multiple fileds but having issues with it. I want to group by period,productcode.
var ProductUsageSummary = from b in myProductUsage
group b by b.ProductCode into g
select new
{
Period = g.Key,
Code = g.Key,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
also tried
var ProductUsageSummary = from b in myProductUsage
group b by b.Period b.ProductCode into g
select new
{
Period = g.Key(n => n.period),
Code = g.Key,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
You could create an anonymouns object to to group on multiple columns (ex... new {prop1 prop2}) , and the grouped fields can be accessed by Key.PropertyName
Try this.
var ProductUsageSummary = from b in myProductUsage
group b by new { b.Period, b.ProductCode }into g
select new
{
Period= g.Key.Period,
Code = g.Key.ProductCode ,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
This is the correct syntax using Anonymous Types :
group b by new { b.ProductCode, b.Period } into g
Then in select:
g.Key.ProductCode and g.Key.Period
Full Query:
var ProductUsageSummary = from b in myProductUsage
group b by new { b.Period b.ProductCode } into g
select new
{
Period = g.Key.Period,
Code = g.Key.ProductCode,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
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();
I have a List with 2 columns with the following structure:
50 process:3333
50 phone:xxxx
51 process:2222
51 phone:yyyy
I need to build a new list based on that first one with this structure:
50 process:3333,phone:xxxx
51 process:2222,phone:yyyy
Does List have any method to find from one column a same value and concatenate the string on second column.
Or I have to find a way to do it manually using a foreach or a while statement?
Assuming a simple struct like...
public struct Proc
{
public int ID { get; set; }
public string Value { get; set; }
}
with your sample data:
var procList = new List<Proc>() {
new Proc{ID=50,Value="process:3333"},new Proc{ID=50,Value="phone:xxxx"},
new Proc{ID=51,Value="process:2222"},new Proc{ID=51,Value="phone:yyyy"},
};
You can use Enumerable.GroupBy and String.Join:
var procIdGroupList = procList
.GroupBy(p => p.ID)
.Select(g => new Proc
{
ID = g.Key,
Value = string.Join(",", g.Select(p => p.Value))
}).ToList();
DEMO
Found a workaround for that:
//Recupera valores dos indices para o tipo de documento
List<Gedi.Models.OperacoesModel.imports> valuesList = new List<Gedi.Models.OperacoesModel.imports>();
var valuesListObj = from a in context.sistema_Documentos
join b in context.sistema_Indexacao on a.id equals b.idDocumento
join c in context.sistema_Indexes on b.idIndice equals c.id
where a.ativo == 1
select new
{
id = a.id,
values = c.idName + ":" + b.valor
};
var çist = (from x in valuesListObj.AsEnumerable()
select new Gedi.Models.OperacoesModel.imports
{
id = x.id,
values = x.values
}).ToList();
var importList = çist.GroupBy(p => p.id).Select(g => new Gedi.Models.OperacoesModel.imports
{
id = g.Key,
values = string.Join(",", g.Select(p => p.values))
}).ToList();
I have a table, generated from a LINQ query on a datatable, which has subcategory and category fields:
Name...........Category.........Subcategory
Kiss...........Rock.............Glam Rock
Metallica......Rock.............Hard Rock
Bon Jovi.......Rock.............Soft Rock
Slade..........Rock.............Glam Rock
Meatloaf.......Rock.............Soft Rock
Wilee..........Dance............Grime
Mgmt...........Dance............Nu Rave
Dizee..........Dance............Grime
The LINQ query I am using to generate this table is:
var qCategory = from c in dtCategory.AsEnumerable()
select new {
Artist = c.Field<string>("Artist"),
Category = c.Field<string>("Category"),
Subcategory = c.Field<string>("Subcategory")
};
Now I want to get a count of each category/subcategory pair. e.g. for the above example I want to return:
Category............Subcategory.......Count
Rock................Glam Rock.........2
Rock................Soft Rock........2
Rock................Hard Rock.........1
Dance...............Grime.............2
Dance...............Nu Rave...........1
How can I acheive this?
Try:
var counts = from artist in qCategory
group artist by new { artist.Category, artist.Subcategory }
into g
select new {
g.Key.Category,
g.Key.Subcategory,
Count = g.Count()
};
If you want to enforce that subcategories always have the same parent category (given that the sub-categories are named "Glam Rock" etc., I assume that this is in fact the case), do:
var counts = from artist in qCategory
group artist by artist.Subcategory into g
select new {
Category = g.Select(a => a.Category)
.Distinct()
.Single(),
Subcategory = g.Key,
Count = g.Count()
};
This will throw an exception if "Rap Rock" turns up as a subcategory of both "Rap" and "Rock".
qCategory.
GroupBy(item => new {Category = item.Category, Subcategory = item.Subcategory}).
Select(group => new {Category = group.Key.Category, Subcategory = group.Key.Subcategory, Count = group.Count()})