Can someone help me here with some hints. Basically I would like to apply different aggregate functions (Count, Sum, Min) on different fields to the entire set (not really groupping), and return the results as fields in an anonymous type. Something like:
var employees = new[] {
new { Name = "John Smith", Gender="M", DateOfHiring=new DateTime(2004, 10, 22), Salary=60000 },
new { Name = "Jane Smith", Gender="F", DateOfHiring=new DateTime(2008, 5, 22), Salary=55000 },
new { Name = "Kathleen Smith", Gender="F", DateOfHiring=new DateTime(2006, 10, 22), Salary=75000 },
new { Name = "David Smith", Gender="M", DateOfHiring=new DateTime(2002, 7, 12), Salary=85000 },
new { Name = "Mary Smith", Gender="F", DateOfHiring=new DateTime(2009, 6, 15), Salary=55000 }
};
var query = from e in开发者_C百科 employees
select new {
NumberOfMaleEmployees = /* Count Where Gender = 'M' */,
NumberOfFemaleEmployees = /* Count Where Gender = 'F' */,
TotalSalaries = /* Sum All */,
AverageSalary = /* Avg All */,
LatestEmployee = /* Employee with Min DateOfHiring */
};
Is it possible to achieve this in one query? Thanks in advance Iulian
While Mr. Skeet's answer works, it does cause employees
to be iterated 5 times (including the "latest employee".) You're probably better off with a straight for
loop that tracks each aggregation of interest:
int maleCount = 0;
int femaleCount = 0;
long totalSalary = 0;
double averageSalary = 0.0;
object latestEmployee = null;
for (int i = 0; i < employees.Length; i++)
{
maleCount += (employees[i].Gender == "M") ? 1 : 0;
totalSalary += employees[i].Salary;
if (latestEmployee == null || employees[i].HireDate > latestEmployee.HireDate)
{
latestEmployee = employees[i];
}
}
femaleCount = employees.Length - maleCount;
averageSalary = totalSalary / (double)employees.Length;
I've assumed that employees can be either male or female; you'd need to adjust your code if that assumption isn't warranted.
You don't want to be iterating over the array to start with by the looks of it - you just want:
var query = new {
NumberOfMaleEmployees = employees.Count(x => x.Gender == "M"),
NumberOfFemaleEmployees = employees.Count(x => x.Gender == "F"),
TotalSalaries = employees.Sum(x => x.Salary),
AverageSalary = employees.Average(x => x.Average),
};
The "latest employee" bit is slightly tricky - you basically want MaxBy
from MoreLINQ, which would let you write:
LatestEmployee = employees.MaxBy(x => x.DateOfHiring)
(which you can include in the above query, of course).
精彩评论