How to group by multiple columns with joins using linq - linq

How to group by multiple columns coming from different tables and finally sum the amount column
var result = _employeeDAL.GetList(db =>
from es in db.Set<EmployeeSchedule>()
join est in db.Set<EmployeeSalaryType>() on est.Employee_Id equals es.Employee_Id
join et in db.Set<EmployeeType>() on est.Employee_Salary_Id equals et.Employee_Salary_Id
where es.Status == "JOINED" && es.JoinedDate.Year == 2017
select new
{
EmployeeName = es.EmployeeName
,Amount = est.Amount ///----------> SUM THIS
,EmployeeType = et.EmployeeType
});
Here's WHat I have tried
var result = _employeeDAL.GetList(db =>
from es in db.Set<EmployeeSchedule>()
join est in db.Set<EmployeeSalaryType>() on est.Employee_Id equals es.Employee_Id
join et in db.Set<EmployeeType>() on est.Employee_Salary_Id equals et.Employee_Salary_Id
group new { es, est, et } by new { es.EmployeeName, et.EmployeeType } into grp
where es.Status == "JOINED" && es.JoinedDate.Year == 2017
select new
{
EmployeeName = es.EmployeeName
,Amount = grp.Sum(g=>g.est.Amount)
,EmployeeType = et.EmployeeType
});

You are almost there. Just need to take into account that after the group ... by ... into grp clause the only variable in scope is grp.
So move the where clause before the group by and use grp.Key inside the select:
var result = _employeeDAL.GetList(db =>
from es in db.Set<EmployeeSchedule>()
join est in db.Set<EmployeeSalaryType>() on est.Employee_Id equals es.Employee_Id
join et in db.Set<EmployeeType>() on est.Employee_Salary_Id equals et.Employee_Salary_Id
where es.Status == "JOINED" && es.JoinedDate.Year == 2017
group new { es, est, et } by new { es.EmployeeName, et.EmployeeType } into grp
select new
{
EmployeeName = grp.Key.EmployeeName,
Amount = grp.Sum(g => g.est.Amount),
EmployeeType = grp.Key.EmployeeType,
});

Related

Linq multi level grouping

I am trying to implement a multi level grouping in linq
In sql it would be something like that.
Select VarId, variable, UT ,
(case when resultat >= 0 then sum(resultat) else 0) as Positive,
(case when resultat < 0 then sum(resultat) else 0) as Negatif
from
(Select VarId, variable, UT , valeur, sum( resultat ) from IndicRow
group by VarId, variable, UT , valeur)
group by VarId, variable, UT
i have created that in linq but i can't find the way to group on the result of a group by
var Chartline = from IndicRow in Indic_dt.AsEnumerable()
//where SelTradeId.Contains(IndicRow.Field<int>("TradeNum"))
group IndicRow by new
{
GpVariable = IndicRow.Field<string>("Variable"),
GpUT = IndicRow.Field<string>("UT"),
GPVarId = IndicRow.Field<int>("VarId"),
GPValue = IndicRow.Field<double>("Valeur")
} into RdVal
select new
{
VarId = RdVal.Key.GPVarId,
Variable = RdVal.Key.GpVariable,
UT = RdVal.Key.GpUT,
Valeur = RdVal.Key.GPValue,
Resultat = RdVal.Sum(IndicRow => IndicRow.Field<double>("Resultat_EuroNet"))
};
The final goal is to obtain a 5 columns Datatable (VarId, variable, UT, Positive, negative)
The general pattern fro a two-level grouping is
from t in Mains
group t by t.GroupProperty1 into mainGroup
select new { mainGroup.Key,
MainCount = mainGroup.Count(),
subGroups = from mg in mainGroup
group mg by mg.GroupProperty2 into subGroup
select new { subGroup.Key,
SubCount = subGroup.Count()
}
}
So the main grouping is by VarId, variable, UT and the sub grouping only by valeur, because the sub group only contains items of one main group.

how use multiple join in linq?

var abc1 = from dlist in db.DebtorTransactions.ToList()
join war in db.Warranties on dlist.ProductID equals war.Id
join ag in db.Agents on war.fldAgentID equals ag.pkfAgentID
join sr in db.SalesReps on war.fldSrId equals sr.pkfSrID
where dlist.TransTypeID == 1
select new
{
dlist.Amount,
dlist.TransTypeID,
name = ag.Name,
ag.pkfAgentID,
sr.pkfSrID,
salesnam = sr.Name
} into objabc
group objabc by new
{
objabc.TransTypeID,
objabc.name,
objabc.salesnam,
objabc.Amount
};
var amt1 = abc1.Sum(x => x.Key.Amount);
var abc2 = from dlist in db.DebtorTransactions.ToList()
join cjt in db.CarJackaTrackas on dlist.ProductID equals cjt.pkfCjtID
join ag in db.Agents on cjt.AgentID equals ag.pkfAgentID
join sr in db.SalesReps on cjt.SalesRepId equals sr.pkfSrID
where dlist.TransTypeID == 0
select new
{
dlist.Amount,
dlist.TransTypeID,
name = ag.Name,
ag.pkfAgentID,
sr.pkfSrID,
enter code here` salesnam = sr.Name
} into objabc
group objabc by new
{
objabc.TransTypeID,
objabc.name,
objabc.salesnam,
objabc.Amount
};
var amt2 = abc1.Sum(x => x.Key.Amount);
//var result1=
return View();
i am new to linq, this query is working but i need to get the sum of Amount where dlist.TransTypeID == 0 and where dlist.TransTypeID == 1 by just single query. may anybody help me? thanks in advance
Here's a trimmed down example of how you can do it. You can add the joins if they are necessary, but I'm not clear on why you need some of the extra join values.
var transTypeAmountSums = (from dlist in db.DebtorTransactions
group dlist by dlist.TransTypeId into g
where g.Key == 0 || g.Key == 1
select new
{
TransTypeId = g.Key,
AmountSum = g.Sum(d => d.Amount)
}).ToDictionary(k => k.TransTypeId, v => v.AmountSum);
int transTypeZeroSum = transTypeAmountSums[0];
int transTypeOneSum = transTypeAmountSums[1];
A couple of things to note:
I removed ToList(). Unless you want to bring ALL DebtorTransactions into memory then run a Linq operation on those results, you'll want to leave that out and let SQL take care of the aggregation (it's much better at it than C#).
I grouped by dlist.TransTypeId only. You can still group by more fields if you need that, but it was unclear in the example why they were needed so I just made a simplified example.

how to combine two linq to entity queries in just one query?

var CJTDebTransaction = from d in db.DebtorTransactions
join c in db.CarJackaTrackas on d.ProductID equals c.pkfCjtID
join a in db.Agents on c.AgentID equals a.pkfAgentID
join s in db.SalesReps on c.SalesRepId equals s.pkfSrID
where d.TransTypeID==1 && d.Product==1
select new { d.Amount, d.TransTypeID, Name=a.Name.Trim(), a.pkfAgentID,s.pkfSrID,salesrepName=s.Name} into debtRec
group debtRec by new { debtRec.TransTypeID, debtRec.Name, debtRec.pkfAgentID,debtRec.salesrepName,debtRec.pkfSrID} into debtRecGroup
orderby debtRecGroup.Key.Name
select new
{
Sum= debtRecGroup.Sum(model=>model.Amount),
TransTypeId=debtRecGroup.Key.TransTypeID ,
AgentId=debtRecGroup.Key.pkfAgentID,
AgentName=debtRecGroup.Key.Name,
SalesrepId=debtRecGroup.Key.pkfSrID,
SalesRepName=debtRecGroup.Key.salesrepName
};
var WntyDebTransaction = from d in db.DebtorTransactions
join w in db.Warranties on d.ProductID equals w.Id
join a in db.Agents on w.fldAgentID equals a.pkfAgentID
join s in db.SalesReps on w.fldSrId equals s.pkfSrID
where d.TransTypeID == 1 && d.Product == 0
select new { d.Amount, d.TransTypeID, Name=a.Name.Trim(), a.pkfAgentID, s.pkfSrID, salesrepName = s.Name } into debtRec
group debtRec by new { debtRec.TransTypeID, debtRec.Name, debtRec.pkfAgentID, debtRec.salesrepName, debtRec.pkfSrID } into debtRecGroup
orderby debtRecGroup.Key.Name
select new
{
Sum = debtRecGroup.Sum(model => model.Amount),
TransTypeId = debtRecGroup.Key.TransTypeID,
AgentId = debtRecGroup.Key.pkfAgentID,
AgentName = debtRecGroup.Key.Name.Trim(),
SalesrepId = debtRecGroup.Key.pkfSrID,
SalesRepName = debtRecGroup.Key.salesrepName
}
I need to get the output in just one query, i new to linq to entity. i need the result like:- AgentName SalesRepName Debit Total(the total of amount where Product == 0) Credit Total(total of amount where Product==1) Outstanding Total(the difference between Debit Total and Credit Total). any suggestion will be appreciable. thanks in advance :)

LINQ 2 lefts joins with Sum

I am trying to do a relatively straight forward SQL query with linq:
SELECT ir.resource_id, r.first_name, r.surname, rt.job_title, SUM(plan_ts_hours), SUM(ts_hours) FROM tbl_initiative_resource ir
INNER JOIN tbl_resource r ON ir.resource_id = r.resource_id
INNER JOIN tbl_resource_type rt ON rt.resource_type_id = r.resource_type_id
LEFT JOIN tbl_plan_timesheet pts on pts.resource_id = ir.resource_id AND pts.initiative_id = ir.initiative_id
LEFT JOIN tbl_timesheet ts on ts.resource_id = ir.resource_id AND ts.initiative_id = ir.initiative_id
WHERE ir.initiative_id = 111
GROUP BY ir.resource_id, r.first_name, r.surname, rt.job_title
After reading this blog: http://smehrozalam.wordpress.com/2010/04/06/linq-how-to-build-complex-queries-utilizing-deferred-execution-and-anonymous-types/
I came up with the following linq:
var query = (from initRes in Context.tbl_initiative_resource
join res in Context.tbl_resource on initRes.resource_id equals res.resource_id
join resType in Context.tbl_resource_type on res.resource_type_id equals resType.resource_type_id
from tsheet in Context.tbl_timesheet.Where(x => x.resource_id == initRes.resource_id).Where(x => x.initiative_id == initRes.initiative_id).DefaultIfEmpty()
from plannedtsheet in Context.tbl_plan_timesheet.Where(x => x.resource_id == initRes.resource_id).Where(x => x.initiative_id == initRes.initiative_id).DefaultIfEmpty()
where initRes.initiative_id == initiativeID
group new { ID = res.resource_id, ResourceType = resType.job_title, Times = tsheet, P = plannedtsheet } by initRes.resource_id into g
select new
{
ResourceID = g.Key,
Hours = g.Sum(x => (decimal?)x.Times.ts_hours),
PlannedHours = g.Sum(x => (decimal?)x.P.plan_ts_hours)
}).ToList();
Any ideas on how I can access the ResourceType when selecting the new anonymous type?
ResourceType is part of the the grouping key, so g.Key.ResourceType should do it.
(Check out the type of ResouceID in the results, as you've assigned it g.Key it will be an instance of the (anonymous) type created in the group clause.

Linq left outer join across multiple tables retrieving info from each table

I am new to linq and want to perform joins across three tables. The sql equivalent of what I am trying to do is:
SELECT PM.Id, PM.new_clientId, .....
C.new_firstname, c.new_surname,.....
A.new_addressid, A.new_addressline1, A.new_addressline2.....
CY.new_county
FROM partialMatch PM
INNER JOIN new_client C ON PM.new_clientId = C.new_clientId
LEFT OUTER JOIN new_address A ON C.new_addressId = A.new_addressId
LEFT OUTER JOIN new_county CY ON A.new_countyId = CY.new_countyId
WHERE PM.ownerId = #UserId AND PM.new_reviewed <> true
The linq code I have developed is this, but these don't seem to be outer join as it is not returning any results unless I comment out the joins to the address and county table
var partialMatches = from pm in ContextService.CreateQuery<new_partialmatch>()
join c in ContextService.CreateQuery<new_client>() on pm.new_ClientId.Id equals c.new_clientId
join a in ContextService.CreateQuery<new_address>() on c.new_AddressID.Id equals a.new_addressId
join cy in ContextService.CreateQuery<new_county>() on a.new_CountyID.Id equals cy.new_countyId
where pm.OwnerId.Id == _currentUserId && pm.new_Reviewed != true
select new
{
Id = pm.Id,
new_ClientID = pm.new_ClientId,
new_MatchingCRMClientID = pm.new_MatchingCRMClientId,
new_MatchingVulcanClientID = pm.new_MatchingVulcanClientID,
new_name = pm.new_name,
firstname = c.new_FirstName,
surname = c.new_Surname,
dob = c.new_DateOfBirth,
addressId = a.new_addressId,
address1 = a.new_AddressLine1,
address2 = a.new_AddressLine2,
address3 = a.new_AddressLine3,
address4 = a.new_AddressLine4,
county = cy.new_County
};
Any help would be greatly appreciated,
Thanks,
Neil
EDIT:
I also tried using the 'into' statement but then on my second join the alias isn't recognised.
from pm in ContextService.CreateQuery<new_partialmatch>()
join c in ContextService.CreateQuery<new_client>() on pm.new_ClientId.Id equals c.new_clientId into pmc
from x in pmc.DefaultIfEmpty()
join a in ContextService.CreateQuery<new_address>() on c.new_AddressID.Id equals a.new_addressId
So for the c.newIddressID.Id equals a.new_addressId I get this error message:
The name 'c' is not in scope on the left side of 'equals'. Consider swapping the expressions on either side of 'equals'.
var addressCountryQuery = from a in ContextService.CreateQuery<new_address>()
from cy in ContextService.CreateQuery<new_county>().Where( cy => cy.new_countyId == a.new_CountyID.Id).DefaultIfEmpty()
select new
{
addressId = a.new_addressId,
address1 = a.new_AddressLine1,
address2 = a.new_AddressLine2,
address3 = a.new_AddressLine3,
address4 = a.new_AddressLine4,
county = cy.new_County
}
var partialMatches = from pm in ContextService.CreateQuery<new_partialmatch>()
join c in ContextService.CreateQuery<new_client>() on pm.new_ClientId.Id equals c.new_clientId
from a in addressCountryQuery .Where( a => a.addressId == c.new_AddressID.Id).DefaultIfEmpty()
where pm.OwnerId.Id == _currentUserId && pm.new_Reviewed != true
select new
{
Id = pm.Id,
new_ClientID = pm.new_ClientId,
new_MatchingCRMClientID = pm.new_MatchingCRMClientId,
new_MatchingVulcanClientID = pm.new_MatchingVulcanClientID,
new_name = pm.new_name,
firstname = c.new_FirstName,
surname = c.new_Surname,
dob = c.new_DateOfBirth,
addressId = a.addressId,
address1 = a.AddressLine1,
address2 = a.AddressLine2,
address3 = a.AddressLine3,
address4 = a.AddressLine4,
county = a.County
};
See how I modified the join for a and cy so I could add the DefultIfEmpty method.
I split the two outer joins in to one query and then join that query back into the original query.

Resources