Find average salary of a department using LINQ - c#

How do I find the average salary for each department?
var employees = new List<Employee>
{
new Employee {Name = "Tom", Age = 32,Department = "Design",Salary=120000},
new Employee {Name = "John", Age = 22,Department = "UI",Salary=86000},
new Employee {Name = "Sandra", Age = 36,Department = "UI",Salary=83000},
new Employee {Name = "Julie", Age = 54,Department = "Javascript",Salary=80000},
new Employee {Name = "Samantha", Age = 21,Department = "Design",Salary=125000}
};
var massagedEmployees = employees.GroupBy(e => e.Department).Select(g=>g.??????
In SQL I would do something like
select Department,avg(salary) from Employees group by Department

You can use:
var massagedEmployees = employees.GroupBy(e => e.Department)
.Select(g => new { Department = g.Key, Avg = g.Average(e => e.Salary) } );

var massagedEmployees = employees.GroupBy(e => e.Department)
.Select(g=>g.Average(x=>x.Salary));
You should include the Department key like this:
var massagedEmployees = employees.GroupBy(e => e.Department)
.Select(g=>
new {
Department = g.Key,
SalaryAvg = g.Average(x=>x.Salary)
});

var massagedEmployees = employees
.GroupBy(e => e.Department)
.Select(p=> new {p.Key, p.Average(q=>q.Salary)};

employees.Where(e => e.Department == "[department]")
.Average(e => e.Salary);

var massagedEmployees =
employees.GroupBy(e => e.Department).Select(c => new {Dep = c.Key, Sum = c.Sum(i => i.Salary)/c.Count()});

Actually you can simplify it to a single operator unlike the previous GroupBy answers GroupBy has an overload just for that so that you don't need the following select:
employees.GroupBy(e=>e.Department,items=>items.Average(e=>e.Salary))

Related

LINQ Method - Optimization

I'm reading a CSV file splitting it into cols, then grouping into a new class.
It looks clunky just wondering is there is a more simple method for instance like not selecting them into the class first:
EDIT: so to clarify I'm trying to get the TimesheetHours grouped by all the other columns.
var rowList = csvFile.Rows.Select(row => row.Split(','))
.Select(cols => new UtilisationRow {
UploadId = savedUpload.Id,
FullName = cols[0],
TimesheetWorkDateMonthYear = Convert.ToDateTime(cols[1]),
TimesheetTaskJobnumber = cols[2],
TimesheetWorktype = cols[3],
TimesheetHours = Convert.ToDouble(cols[4]),
TimesheetOverhead = cols[5]
})
.GroupBy(d => new {
d.FullName,
d.TimesheetWorkDateMonthYear,
d.TimesheetTaskJobnumber,
d.TimesheetWorktype,
d.TimesheetOverhead
})
.Select(g => new UtilisationRow {
FullName = g.First().FullName,
TimesheetWorkDateMonthYear = g.First().TimesheetWorkDateMonthYear,
TimesheetTaskJobnumber = g.First().TimesheetTaskJobnumber,
TimesheetWorktype = g.First().TimesheetWorktype,
TimesheetHours = g.Sum(s => s.TimesheetHours),
TimesheetOverhead = g.First().TimesheetOverhead
})
.ToList();
Many thanks,
Lee.
The two problems in your code are that you call First() repeatedly on a group, while you should retrieve that same data from group's key, and that you are using UtilisationRow in the first Select, which should use an anonymous type instead:
var rowList = csvFile.Rows.Select(row => row.Split(','))
.Select(cols => new {
UploadId = savedUpload.Id,
FullName = cols[0],
TimesheetWorkDateMonthYear = Convert.ToDateTime(cols[1]),
TimesheetTaskJobnumber = cols[2],
TimesheetWorktype = cols[3],
TimesheetHours = Convert.ToDouble(cols[4]),
TimesheetOverhead = cols[5]
})
.GroupBy(d => new {
d.FullName,
d.TimesheetWorkDateMonthYear,
d.TimesheetTaskJobnumber,
d.TimesheetWorktype,
d.TimesheetOverhead
})
.Select(g => new UtilisationRow {
FullName = g.Key.FullName,
TimesheetWorkDateMonthYear = g.Key.TimesheetWorkDateMonthYear,
TimesheetTaskJobnumber = g.Key.TimesheetTaskJobnumber,
TimesheetWorktype = g.Key.TimesheetWorktype,
TimesheetHours = g.Sum(s => s.TimesheetHours),
TimesheetOverhead = g.Key.TimesheetOverhead
})
.ToList();
Now the "pipeline" of your method looks pretty clean:
The first Select does the initial parsing into a temporary record
GroupBy bundles matching records into a group
The final Select produces records of the required type.

Why this linq query doesn't return distinct code?

I want list of all unique Scheme_Codes but I am unable to write query. I tried this one but I am confused what's problem with this query.
var queryresult = db.MFData.GroupBy(x => new { Scheme_Name = x.Scheme_Name, Scheme_Code = x.Scheme_Code, FundFamily = x.FundFamily, Date = x.Date })
.Select(group => new
{
Scheme_name = group.Key.Scheme_Name,
Scheme_Code = group.Key.Scheme_Code,
FundFamily = group.Key.FundFamily,
Date = group.Max(x => x.Date),
count = group.Select( x => x.Scheme_Code).Distinct().Count()
}
).OrderBy(x => x.Scheme_Code);
I have this query but I am not sure how to convert this to linq
SELECT [Scheme_Code],[FundFamily],[Scheme_Name],
MAX([Date]) as LastDate
FROM [MFD].[dbo].[MFDatas]
GROUP BY [Scheme_Code],[Scheme_Name], [FundFamily]
ORDER BY [Scheme_Code]
All you have to do is omit the date from your groupby-clause:
var queryresult = db.MFData.GroupBy(x => new
{
Scheme_Name = x.Scheme_Name,
Scheme_Code = x.Scheme_Code,
FundFamily = x.FundFamily
}).Select(group => new
{
Scheme_name = group.Key.Scheme_Name,
Scheme_Code = group.Key.Scheme_Code,
FundFamily = group.Key.FundFamily,
Date = group.Max(x => x.Date),
count = group.Select(x => x.Scheme_Code).Distinct().Count()
}).OrderBy(x => x.Scheme_Code);

LINQ not sorting List<> properly

My EF query is supposed to be sorting by the date of the first Product in the list, but for some reason, it only sorts most of the products and some of the dates are in the wrong order.
Here's the code...
using (var context = new SalesEntities())
{
var groupedData = context.s84_Schedule.AsExpandable()
.Where(predicate)
.GroupBy(c => new { c.CustomerID, c.s84_Customer.CustomerName, c.SubdivisionID, c.s84_Subdivision.SubdivisionName, c.LotNumber })
.Select(grouped => new s84_Report_Project_POCO
{
CustomerID = grouped.Key.CustomerID,
CustomerName = grouped.Key.CustomerName,
SubdivisionID = grouped.Key.SubdivisionID,
SubdivisionName = grouped.Key.SubdivisionName,
LotNumber = grouped.Key.LotNumber,
Products = grouped.Select(x => new s84_Report_Project_Product
{
ProductID = x.ProductID,
ProductName = x.s84_Product.ProductName,
ProductDate = x.CustomerExpectedDate,
FieldRepID = x.FieldRepID,
FieldRepName = x.s84_FieldRep.FieldRepName,
InstallerID = x.InstallerID,
InstallerName = x.s84_Installer.InstallerName,
StatusID = x.StatusID,
StatusColor = x.s84_Status.StatusColor,
StatusName = x.s84_Status.StatusName,
Completed = x.Completed
}).ToList()
});
var finalList = groupedData.ToList().Where(x => x.Products.Last().Completed == false).ToList();
List<s84_Report_Project_POCO> lst = finalList.OrderBy(x => x.Products.First().ProductDate).ToList();
return lst;
}
Code seems good to me, but look at how one of the dates is out of order...
weird sorting http://www.84sales.com/weird_sort.png
Try doing the order by on the inital select
var groupedData = context.s84_Schedule.AsExpandable()
.Where(predicate)
.GroupBy(c => new { c.CustomerID,
c.s84_Customer.CustomerName,
c.SubdivisionID,
c.s84_Subdivision.SubdivisionName,
c.LotNumber })
.Select(grouped => new s84_Report_Project_POCO
{
CustomerID = grouped.Key.CustomerID,
CustomerName = grouped.Key.CustomerName,
SubdivisionID = grouped.Key.SubdivisionID,
SubdivisionName = grouped.Key.SubdivisionName,
LotNumber = grouped.Key.LotNumber,
Products = grouped
.Select(x => new s84_Report_Project_Product
{
ProductID = x.ProductID,
ProductName = x.s84_Product.ProductName,
ProductDate = x.CustomerExpectedDate,
FieldRepID = x.FieldRepID,
FieldRepName = x.s84_FieldRep.FieldRepName,
InstallerID = x.InstallerID,
InstallerName = x.s84_Installer.InstallerName,
StatusID = x.StatusID,
StatusColor = x.s84_Status.StatusColor,
StatusName = x.s84_Status.StatusName,
Completed = x.Completed
}).OrderBy(x => x.CustomerExpectedDate).ToList()
});
The problem is the .First() function, witch returns the first record, but not necessarly in date order. if you wich to order your grouped datas by date so that the First() function returns the most recent date, you'll need to order your datas before grouping them, and then REorder your results with the First()function :
using (var context = PrimaryConnection.returnNewConnection())
{
var groupedData = context.s84_Schedule.AsExpandable()
.Where(predicate)
.GroupBy(c => new { c.CustomerID, c.s84_Customer.CustomerName, c.SubdivisionID, c.s84_Subdivision.SubdivisionName, c.LotNumber })
.Select(grouped => new s84_Report_Project_POCO
{
CustomerID = grouped.Key.CustomerID,
CustomerName = grouped.Key.CustomerName,
SubdivisionID = grouped.Key.SubdivisionID,
SubdivisionName = grouped.Key.SubdivisionName,
LotNumber = grouped.Key.LotNumber,
Products = grouped
.Select(x => new s84_Report_Project_Product
{
ProductID = x.ProductID,
ProductName = x.s84_Product.ProductName,
ProductDate = x.CustomerExpectedDate,
FieldRepID = x.FieldRepID,
FieldRepName = x.s84_FieldRep.FieldRepName,
InstallerID = x.InstallerID,
InstallerName = x.s84_Installer.InstallerName,
StatusID = x.StatusID,
StatusColor = x.s84_Status.StatusColor,
StatusName = x.s84_Status.StatusName,
Completed = x.Completed
}).Orderby(t => t.CustomerExpectedDate).ToList()
});
var finalList = groupedData.ToList().Where(x => x.Products.Last().Completed == false).ToList();
List<s84_Report_Project_POCO> lst = finalList.OrderBy(x => x.Products.First().ProductDate).ToList();
All SQL queries (and hence Linq queries, when attached to a SQL database) have a random order, unless you sort them.
Products is not sorted - hence it has a random order.
You sort by Products.First(), but Products has a random order, so your sort will also be random.
Make sure Products is sorted within the query, and you should be ok.
Products = grouped.Select(....)
.OrderBy(x => x.ProductDate)
.ToList()

linq group by id and sum of amount getting null(undefined)

var approverlist = _db.ApprvRejClaimTravelCashByApproverIdIPhone(ProjectSession.CompanyUserId, ProjectSession.CompanyId, Status).AsEnumerable().ToList();`
var results =
from item in approverlist
group item by item.ClaimId
into g
select new
{
ClaimId = g.Key,
Name = g.First().Name,
Amount = g.Sum(s => s.Amount),
Description = g.First().Description,
Status = g.First().Status,
CreatedDate = g.First().CreatedDate,
SubmitedDate = g.First().SubmitedDate,
FullName = g.First().FullName,
ApproverStatus = g.First().ApproverStatus,
CurrencySymbol = g.First().CurrencySymbol,
chkbox = g.First().chkbox,
IsHierarchy = g.First().IsHierarchy,
ColumnCategory = g.First().ColumnCategory,
ColumnCategoryCode = g.First().ColumnCategoryCode
};
return Json(results.ToDataSourceResult(request));
getting undefined in column Amount when i bind this result to my kendo mvc grid,,,,any one have idea why this happens ?
Also tried below one but same result undefined :
var results = from x in approverlist
group x.ClaimId by new { x.ClaimId, x.Name, x.Description, x.Status, x.CreatedDate, x.SubmitedDate, x.FullName, x.ApproverStatus, x.CurrencySymbol, x.chkbox, x.IsHierarchy, x.ColumnCategory, x.ColumnCategoryCode }
into g
select new { g.Key.ClaimId, g.Key.Name, Amount = g.Sum(), g.Key.Description, g.Key.Status, g.Key.CreatedDate, g.Key.SubmitedDate, g.Key.FullName, g.Key.ApproverStatus, g.Key.CurrencySymbol, g.Key.chkbox, g.Key.IsHierarchy, g.Key.ColumnCategory, g.Key.ColumnCategoryCode };

Grouping in linq

I have a following list of documents:
List<DocumentInfo> list1 = new List<DocumentInfo>()
{
new DocumentInfo { Name = "Customer1", DocCount = 5 },
new DocumentInfo { Name = "Customer1", DocCount = 10 },
new DocumentInfo { Name = "Customer1", DocCount = 5 },
new DocumentInfo { Name = "Customer2", DocCount = 4 },
new DocumentInfo { Name = "Customer2", DocCount = 6 },
new DocumentInfo { Name = "Customer3", DocCount = 3 }
};
How to group the above list based on 'Name' and sum of 'DocCount' using Linq and store in another list? I want something like following:
Name = "Customer1", DocCount = 20
Name = "Customer2", DocCount = 10
Name = "Customer3", DocCount = 3
var results = list1.GroupBy(i => i.Name)
.Select(g => new
{
Name = g.Key,
DocCount = g.Sum(i => i.DocCount)
});
var list2 = list1.GroupBy(x => x.Name).Select(g => new DocumentInfo()
{
Name = g.Key,
DocCount = g.Sum(x => x.DocCount)
});
Try this:
list1.GroupBy(di => di.Name).Select(g => new DocumentInfo {Name = g.Key, DocCount = g.Sum(dc => dc.DocCount)});
var result= from item in list1
group item by item.Name
into g
select g;
var groupedInfo = result.SelectMany(group => group);
foreach(var g in groupedInfo)
{
//Do Summation
}
Try like this;
var anotherlist = list1.GroupBy(g => g.Name)
.Select(s => new
{
Name = s.Key,
DocCount = s.Sum(i => i.DocCount)
});
It is simply, getting sum of DocCount and their Name properties by grouping based Name.
Here is another way to do the same
var sumOfDocs = from doc in list1 group doc by doc.Name into g
select new { DocName = g.Key, DocSum = g.Sum(i => i.DocCount) };

Categories

Resources