how use multiple join in linq? - 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.

Related

Left joining a table's id with the maximum id from a subquery

I am using .NET core and trying to write a Linq query to list Cases. I have 3 tables that I am trying to join together:
Cases - Includes CaseID and CaseStatusID
CaseStatuses - Includes CaseStatusID (a Case has one of these)
CaseStatusHistory - Includes CaseStatusHistoryID, CaseID, CaseStatusID (a Case has many of these).
I can join Cases and CaseStatuses easily on CaseStatusID but am not sure how to join CaseStatusHistory on CaseStatusHistoryID = a subquery selecting the MAX(CaseStatusHistoryID) WHERE CaseID and CaseStatusID matches. I could even select the CaseStatusHitory later in my results but am not sure how.
This is what I need to convert
SELECT
c.CaseID,
csh.DateTimeAdded
FROM dbo.Cases c
JOIN dbo.CaseStatuses cs
ON c.CaseStatusID = cs.CaseStatusID
LEFT JOIN dbo.CaseStatusHistory csh
ON csh.CaseStatusHistoryID =
(
SELECT MAX(CaseStatusHistoryID)
FROM dbo.CaseStatusHistory
WHERE CaseID = c.CaseID
AND cs.CaseStatusID = c.CaseStatusID
)
This is what I have so far in Linq
IQueryable<CasesViewModel> objs =
from c in _db.Cases
from cs in _db.CaseStatuses.Where(cs => cs.CaseStatusId == c.CaseStatusId.Value).DefaultIfEmpty()
select new CasesViewModel
{
CaseID = c.CaseId,
CaseStatus = cs.CaseStatus
//StatusChangeDate = csh.DateTimeAdded
};
I need to add something like this
From csh In CaseStatusHistories
Where
(
From _csh In CaseStatusHistories
Where _csh.CaseID = c.CaseID AndAlso _csh.CaseStatusID = c.CaseStatusID
Select _csh.CaseStatusHistoryID
).Max = csh.CaseStatusHistoryID
Here is what I have so far but it does not return any result - just seems to time out.
IQueryable<CasesViewModel> objs =
from c in _db.Cases
from cs in _db.CaseStatuses.Where(cs => cs.CaseStatusId == c.CaseStatusId.Value).DefaultIfEmpty()
from rg in _db.RepairingGarages.Where(rg => rg.RepairingGarageId == c.RepairingGarageId.Value).DefaultIfEmpty()
from rgb in _db.Businesses.Where(rgb => rgb.BusinessId == rg.BusinessId.Value).DefaultIfEmpty()
from ec in _db.EngineeringCompanies.Where(ec => ec.EngineeringCompanyId == c.EngineeringCompanyId.Value).DefaultIfEmpty()
from ecb in _db.Businesses.Where(ecb => ecb.BusinessId == ec.BusinessId.Value).DefaultIfEmpty()
from csh in _db.CaseStatusHistory.Where(csh => csh.CaseStatusHistoryId ==
(
from _csh in _db.CaseStatusHistory
where _csh.CaseId == c.CaseId && _csh.CaseStatusId == c.CaseStatusId.Value
select _csh.CaseStatusHistoryId
).Max()).DefaultIfEmpty()
select new CasesViewModel
{
CaseID = c.CaseId,
RepairingGarage = rgb.BusinessName,
Engineer = ecb.BusinessName,
CaseStatus = cs.CaseStatus,
StatusChangeDate = csh.DateTimeAdded
};
I just need to get the StatusChangeDate which is the DateTimeAdded in the CaseStatusHistory table. Cases can be at the same status more than once, so I just need the DateTimeAdded with the highest CaseStatusHistoryID for a particular Case. Thank you very much for any help.
This appears to answer my question
IQueryable<CasesViewModel> objs =
from c in _db.Cases
from cs in _db.CaseStatuses.Where(cs => cs.CaseStatusId == c.CaseStatusId.Value).DefaultIfEmpty()
from rg in _db.RepairingGarages.Where(rg => rg.RepairingGarageId == c.RepairingGarageId.Value).DefaultIfEmpty()
from rgb in _db.Businesses.Where(rgb => rgb.BusinessId == rg.BusinessId.Value).DefaultIfEmpty()
from ec in _db.EngineeringCompanies.Where(ec => ec.EngineeringCompanyId == c.EngineeringCompanyId.Value).DefaultIfEmpty()
from ecb in _db.Businesses.Where(ecb => ecb.BusinessId == ec.BusinessId.Value).DefaultIfEmpty()
select new CasesViewModel
{
CaseID = c.CaseId,
RepairingGarage = rgb.BusinessName,
Engineer = ecb.BusinessName,
CaseStatus = cs.CaseStatus,
StatusChangeDate =
(
from _csh in _db.CaseStatusHistory
where _csh.CaseId == c.CaseId && _csh.CaseStatusId == cs.CaseStatusId
orderby _csh.CaseStatusHistoryId descending
select _csh.DateTimeAdded
).FirstOrDefault()
};
The only trouble with not joining is that I am not sure if I can sort by this date now. Any better ideas? Thank you.

Linq to SQL conversion...unable to add second COUNT

I'm trying to convert my SQL statement to a Linq statement and I'm not sure how to add the second COUNT to it. This is my SQL statement
SELECT l.Campus_Name, Labs = COUNT(*), LabsWithSubnets = COUNT(s.Lab_Space_Id)
FROM vw_Lab_Space l
LEFT JOIN vw_Subnet s on l.Lab_Space_Id = s.Lab_Space_Id
GROUP BY l.Campus_Name
ORDER BY 1
and this is my LINQ statement so far:
from l in Vw_Lab_Space
from s in Vw_Subnet
.Where(s => s.Lab_Space_Id == l.Lab_Space_Id)
.DefaultIfEmpty() // <=- triggers the LEFT JOIN
group l by new { l.Campus_Name } into g
orderby g.Key.Campus_Name
select new {
Campus_Name = g.Key.Campus_Name,
Labs = g.Count()
}
So I have everything but the LabsWithSubnets part in there. I'm just not sure how to add that in as I can't just do an s.Lab_Space_id.Count() in the select statement.
If you need table structure and sample data please see Need help creating an OUTER JOIN to count spaces.
Using your query as a basis, you need the groups to include s so you can count when non-null (I also removed the unnecessary anonymous object around the grouping key):
from l in Vw_Lab_Space
from s in Vw_Subnet
.Where(s => s.Lab_Space_Id == l.Lab_Space_Id)
.DefaultIfEmpty() // <=- triggers the LEFT JOIN
group new { l, s } by l.Campus_Name into g
orderby g.Key
select new {
Campus_Name = g.Key,
Labs = g.Count(),
LabsWithSubnets = g.Count(ls => ls.s != null)
}
However, rather than translate the SQL, I would probably take advantage of LINQ's group join to handle the query slightly differently:
var ans = from l in Vw_Lab_Space
join s in Vw_Subnet on l.Lab_Space_Id equals s.Lab_Space_Id into sj
group new { l, sj } by ls.Campus_Name into lsjg
select new {
Campus_Name = lsjg.Key,
NumLabs = lsjg.Count(),
LabsWithSubnets = lsjg.Sum(lsj => lsj.sj.Count())
};
PS Even in your query, I would use join...from...DefaultIfEmpty rather than from...from...where but depending on your database engine, may not matter.

How do I outer join and group by in Entity framework Linq?

I'm having trouble getting my Linq statemnt to work when doing an outer join and a group by. Here's a SQL version of what I'm trying to accomplish:
select p.PRIMARY_KEY, min(p.EFFECTIVE_DATE), sum(IsNull(c.PAID_INDEMNITY, 0))
from PRMPOLCY p
left outer join CLMMAST c on p.PRIMARY_KEY = c.POLICY_NO
where p.UNDERWRITER_UID = 93
GROUP BY p.PRIMARY_KEY
Here's what I have in Linq (which doesn't work):
var result = from p in context.PRMPOLCies
join c in context.CLMMASTs on p.PRIMARY_KEY equals c.POLICY_NO into polClm
where (p.UNDERWRITER_UID == underwriter)
from grp in polClm.DefaultIfEmpty()
group grp by p.PRIMARY_KEY into g
select new PolicySummation()
{
PolicyNo = g.Key,
Incurred = g.Sum(grp => grp.PAID_INDEMNITY ),
EffDate = g.Min(grp => grp.PRMPOLCY.EFFECTIVE_DATE
};
Beating my head against the wall trying to figurwe this out!
Assuming you have a navigation property set up between PRMPOLCY and CLMMAST, you shouldn't need to specify the join explicitly. It's much easier to express most queries in linq without explicit joins, but rather treating your structures as a hierarchy. I don't know the specifics of your model property names, but I'd take a guess that something like this would work.
var result =
from p in context.PRMPOLCies
where (p.UNDERWRITER_UID == underwriter)
select new PolicySummation {
PolicyNo = p.PRIMARY_KEY,
Incurred = p.CLMASTs.Select(c => c.PAID_INDEMNITY).DefaultIfEmpty().Sum(),
EffDate = p.EFFECTIVE_DATE,
};
You need to include both your tables in the group clause like this:
group new { p, grp } by p.PRIMARY_KEY into g
Then in your Sum / Min
g.Sum(grp => grp.grp == null ? 0 : grp.grp.PAID_INDEMNITY )
g.Min(grp => grp.p.PRMPOLCY.EFFECTIVE_DATE)

In join want to get not matched records

Work on DF 4 vs 2010.Face problem on join on SalSalesOrderDetail with SalSalesOrderFinancial table.
In SalSalesOrderFinancial one record have SalesOrderDetailID=null. Want to get those records whose SalesOrderDetailID is not present in SalSalesOrderFinancial.
To get desired out put write bellow linq syntax,it’s working .Looking for better join syntax .Is there any way to get desired in one join.
var tempBDwithSODetail = (from p in this.Context.SalSalesOrderFinancials
where p.SalesOrderDetailID != null
select p.SalesOrderDetailID).AsEnumerable();
var tempBDwithOutSODetail = (from p in this.Context.SalSalesOrderFinancials where p.SalesOrderDetailID == null select p).AsEnumerable();
var querySOD = (this.Context.SalSalesOrderDetails.Where(item => !tempBDwithSODetail.Contains(item.SalesOrderDetailID))).AsEnumerable();
var tempBDetail = (from p in querySOD
join q in tempBDwithOutSODetail on p.SalesOrderID equals q.SalesOrderID
where q.SalesOrderDetailID == null
select new
{
q.SalesOrderID,
p.SalesOrderDetailID,
q.CurrencyID,
q.BillingPolicyID,
q.BillTypeID,
q.BillingTypeID
}).AsEnumerable();
If have any query please ask.Thanks in advanced.
if i got you, you just need to simple left join between SalSalesOrderDetail and SalSalesOrderFinancial...
var query = (from u in this.Context.SalSalesOrderDetail
join t in this.Context.SalSalesOrderFinancials
on u.SalesOrderDetailID equals t.SalesOrderDetailID into JoinedList
from t in JoinedList.DefaultIfEmpty()
select new
{
SalSalesOrderDetail = t,
SalSalesOrderFinancials = u
})
.Where(u => u.SalSalesOrderFinancials == null)
.ToList();

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.

Resources