Linq Group & SUM - c#

I really thought I was getting on with linq until now, Ive got a one to many relationship and I need to return the SUM for the Jobitems (jobitems.Cost)
List<Models.Inventory.JobItem> jobItems = BLL.Inventory.JobItem.GetAllActive(forceReload);
List<.Models.Inventory.Job> jobs = BLL.Inventory.Job.GetAllActive(forceReload);
var getInvoicedItems2 = from j in jobs
join ji in jobItems on j.JobId equals ji.JobId
select new { JobCost = ji.Cost, JobId = ji.JobId};
ive got this far but im not sure how to group all by ji.JobId

You can use a group join to group all job items into a set, then take the sum of all costs in that set.
var jobItems = BLL.Inventory.JobItem.GetAllActive(forceReload);
var jobs = BLL.Inventory.Job.GetAllActive(forceReload);
var query = from j in jobs
join ji in JobItems on j.JobId equals ji.JobId into items
select new
{
JobId = j.JobId,
JobCost = items.Sum(ji => ji.Cost),
};

var getInvoicedItems2 = from ji in jobItems
group ji by ji.JobId
into g
select new {JobId = g.Key, Cost = g.Sum(p => p.Cost)};
var getInvoicedItems = from j in jobs
from s in schedules
from i in invoices
from jj in getInvoicedItems2
where i.JobId == j.JobId && j.ScheduleId == s.ScheduleId && jj.JobId == j.JobId
select new { JobCost = jj.Cost, InvoiceDate = i.CreatedDate, Status = i.Status, };
Seems to work

Related

LINQ: Multiple Join With Max Revision Filter

So I have this line:
var transrevmax = db.TRANSACTs
.Where(x => x.SITE == "1" &&
x.DATE_IN >= dateinchoice &&
x.DATE_OUT <= dateoutchoice)
.GroupBy(x => x.TICKET_NO)
.Select(x => x.OrderByDescending(y => y.REV_NO).FirstOrDefault())
.ToList();
and it returns the exact list of transactions I want the join below to go through to obtain values from...
var exportrecovery = (from trans in transrevmax
join detail in db.DETAILs on new { TICKET_NO = trans.TICKET_NO, REV_NO = trans.REV_NO } equals new { TICKET_NO = detail.TICKET_NO, REV_NO = detail.REV_NO }
join job in db.JOBs on new { JOB_CODE = trans.JOB_CODE, CUST_CODE = trans.CUST_CODE } equals new { JOB_CODE = job.CODE, CUST_CODE = job.CUST_CODE }
join customer in db.CUSTOMERs on trans.CUST_CODE equals customer.CODE
join invoiced in db.INVOICEDs on trans.TICKET_NO equals invoiced.TICKET_NO
where trans.DATE_IN >= dateinchoice && trans.DATE_OUT <= dateoutchoice && trans.STATUS.ToString().Trim() != "V" && trans.STATUS.ToString().Trim() != "E"
select new { ADDRESS = customer.ADDRESS, CITY = customer.CITY, STATE = customer.STATE, ZIP = customer.ZIP, FREIGHT = detail.HAUL_CHGE + detail.FUEL_CHGE, JOB_NAME = job.NAME, HAUL_TAX = detail.HAUL_TAX, INVOICE_NO = invoiced.INVOICE_NO, CUST_NAME = customer.NAME, TAX_CODE = customer.TAX_CODE, MAT_CHGE = detail.MAT_CHGE, MAT_TAX = detail.MAT_TAX, MAT_CODE = detail.MAT_CODE, QTY = detail.QTY, PRICE = detail.PRICE, DATE_MOD = trans.DATE_OUT, REV_NO = trans.REV_NO, SITE = trans.SITE, TICKET_NO = trans.TICKET_NO, CUST_CODE = trans.CUST_CODE, JOB_CODE = trans.JOB_CODE }
).ToList();
... if I run the first line I get the transactions limited to only those with the max revision (what I want), and if I run the join (replacing the "transrevmax" with the table "db.TRANSACTs") I get the right range of ticket numbers, but it includes all revisions. I am stumped as to how I can use the joined tables and get only unique rows according to their (maximum) revision number. When these two are used in conjunction I receive zero rows. Please advise.
Remove the ToList on the transrevmax creation.

How to get the group sum in my complex linq query

below I have listed a linq query that works properly in my asp.net.mvc web app.
In addition I would like to group over 'allowance.ParameterId' in order to get the group sum for 'allowance.Freight (instead of multiple records for the given key).
var query = from ara in aras
join company in companies on ara.Id equals company.ARAId
join wasteWater in wasteWaters on company.Id equals wasteWater.CompanyId
join allowance in allowances on wasteWater.Id equals allowance.WasteWaterID
join parameter in parameters on allowance.ParameterId equals parameter.Id into JoinedParameterAllowance
from parameter in JoinedParameterAllowance.DefaultIfEmpty()
where company.Activ == true && company.End == null && company.Template == false
&& wasteWater.End == null
select new FreightSummaryViewModel
{
AraName = ara.Name,
AraId = ara.Id,
AllowedParameter = parameter.Name,
AllowedFreight = allowance.Freight
};
I have tried to insert 'group ...' but failed to get it right.
Could someone help me please to set up the proper syntax?
Thank you in advance, Manu
I have little idea about relations in your database, so I improvised...
// Some dummy data to play with
var aras = Enumerable.Range(0, 5).Select(i => new { Id = i, Name = "Ara" + i });
var companies = Enumerable.Range(0, 15).Select(i => new { Id = i, ARAId = i % 5, Activ = true, End = (DateTime?)null, Template = false });
var wasteWaters = Enumerable.Range(0, 35).Select(i => new { Id = i, CompanyId = i / 15, End = (DateTime?)null });
var allowances = Enumerable.Range(0, 70).Select(i => new { Id = i, WasteWaterID = i, ParameterId = i % 4, Freight = i * 1000 });
var parameters = Enumerable.Range(0, 4).Select(i => new { Id = i, Name = "Parameter" + i });
And this is what I believe you looked for:
var query =
from ara in aras
join company in companies on ara.Id equals company.ARAId
join wasteWater in wasteWaters on company.Id equals wasteWater.CompanyId
join allowance in allowances on wasteWater.Id equals allowance.WasteWaterID
join parameter in parameters on allowance.ParameterId equals parameter.Id
into JoinedParameterAllowance
// from parameter in JoinedParameterAllowance.DefaultIfEmpty()
where true
&& company.Activ == true
&& company.End == null
&& company.Template == false
&& wasteWater.End == null
group allowance by new
{
AraName = ara.Name,
AraId = ara.Id,
ParameterId = allowance.ParameterId
} into myGroup
select new //FreightSummaryViewModel
{
AraName = myGroup.Key.AraName,
AraId = myGroup.Key.AraId,
AllowedParameter = myGroup.Key.ParameterId,
AllowedFreight = myGroup.Sum(g => g.Freight)
};

Split a string value in list using linq

I have a list with a column value like "0000000385242160714132019116002239344.ACK" i need to take last 6 digits from this value like "239344" without extension(.ack) when binding to the list.
And i need to find the sum of Salary field also.
My query looks like below.
var result = from p in Context.A
join e in B on p.Id equals e.Id
join j in Context.C on e.CId equals j.CId
where (e.Date >= periodFrom && e.Date <= periodTo)
group new
{
e,
j
} by new
{
j.J_Id,
e.Date,
e.Es_Id,
e.FileName,
j.Name,
e.ACK_FileName,
p.EmpSalaryId,
p.Salary
} into g
orderby g.Key.CId, g.Key.Es_Id, g.Key.Date, g.Key.FileName
select new
{
CorporateId = g.Key.CId,
ProcessedDate = g.Key.Date,
EstID = g.Key.Es_Id,
FileName = g.Key.FileName,
Name = g.Key.Name,
ack = g.Key.ACK_FileName,
EmpSalaryId = g.Key.EmpSalaryId,
Salary=g.Key.Salary
};
var Abc=result.ToList();
var result = (from p in Context.A
join e in B on p.Id equals e.Id
join j in Context.C on e.CId equals j.CId
where (e.Date >= periodFrom && e.Date <= periodTo)
group new { e, j } by new
{
j.J_Id,
e.Date,
e.Es_Id,
e.FileName,
j.Name,
ACK_FileName = e.ACK_FileName.Substring(e.ACK_FileName.IndexOf(".ACK") - 7, 11),
p.EmpSalaryId,
p.Salary
} into g
orderby g.Key.CId, g.Key.Es_Id, g.Key.Date, g.Key.FileName
select new
{
CorporateId = g.Key.CId,
ProcessedDate = g.Key.Date,
EstID = g.Key.Es_Id,
FileName = g.Key.FileName,
Name = g.Key.Name,
ack = g.Key.ACK_FileName,
EmpSalaryId = g.Key.EmpSalaryId,
Salary = g.Sum(item => item.Salary)
}).ToList();

Not counting null values from a linq LEFT OUTER JOIN query

I have this sql query that does exactly what i want but i need it in linq. It returns a few AVC rows and counts how many PersonAVCPermission that has status 1 linked to it
SELECT a.Id, a.Name, a.Address, COUNT(p.AVCID) AS Count
FROM AVC AS a
LEFT OUTER JOIN
(
SELECT PersonAVCPermission.AVCId
FROM PersonAVCPermission
WHERE PersonAVCPermission.Status = 1
) AS p
ON a.Id = p.AVCId
GROUP BY a.Id, a.Name, a.Address
I have this query in linq and it does the same thing except when there are no PersonAVCPermission it still counts 1
var yellows = odc.PersonAVCPermissions.Where(o => o.Status == (int)AVCStatus.Yellow);
var q = from a in odc.AVCs
from p in yellows.Where(o => o.AVCId == a.Id).DefaultIfEmpty()
group a by new { a.Id, a.Name, a.Address } into agroup
select new AVCListItem
{
Id = agroup.Key.Id,
Name = agroup.Key.Name,
Address = agroup.Key.Address,
Count = agroup.Count(o => o.Id != null)
};
Im guessing that with DefaultIfEmpty() it places null rows in the list that then gets counted so i try to exclude them with (o => o.Id != null) but it still counts everything as at least one
If i dont use DefaultIfEmpty() it skips the rows with count 0 completely
How can i exclude them or am i doing it completely wrong?
How about using .Any() and a Let?
var yellows = odc.PersonAVCPermissions.Where(o => o.Status == (int)AVCStatus.Yellow);
var q = from a in odc.AVCs
let Y = (from p in yellows.Where(o => o.AVCId == a.Id) select p).Any()
where Y == true
group a by new { a.Id, a.Name, a.Address } into agroup
select new AVCListItem
{
Id = agroup.Key.Id,
Name = agroup.Key.Name,
Address = agroup.Key.Address,
Count = agroup.Count(o => o.Id != null)
};
You don't need the join, nor the grouping:
var q = from a in odc.AVCs
select new AVCListItem
{
Id = a.Id,
Name = a.Name,
Address = a.Address,
Count = yellows.Where(o => o.AVCId == a.Id).Count()
};

Linq query with left join and group

I'm unable to convert this SQL query into a working linq statement
select sum(cena), id_auta, max(servis)
from dt_poruchy left outer join mt_auta on dt_poruchy.id_auta=mt_auta.id
where dt_poruchy.servis>=3 group by id_auta;
I tryed something like this but i cant handle the select statement
var auta = from a in MtAuta.FindAll()
join p in DtPoruchy.FindAll() on a equals p.MtAuta into ap
from ap2 in ap.DefaultIfEmpty()
where ap2.SERVIS >= 3
group ap2 by ap2.ID into grouped
select new {
I'll appreciate any help!
Based on the limited information provided (which tables are certain fields from?), here is what I came up with.
var auta = from a in MtAuta.FindAll()
let p = a.DtPoruchys.Where(s => s.SERVIS >= 3)
select new
{
Id = a.Id,
CenaSum = p.Sum(c => c.Cena),
Servis = p.Max(s => s.SERVIS)
};
I've reached this solution (supposing "cena" belongs to MtAuta.FindAll()):
var auta = from e in
(from a in DtPoruchy.FindAll()
where a.SERVIS >= 3
join p in MtAuta.FindAll() on a.MtAuta equals p.Id into ap
from ap2 in ap.DefaultIfEmpty()
select new
{
Cena = ap.cena,
IdAuta = a.MtAuta,
Servis = a.servis
})
group e by e.IdAuta into g
select new
{
Cena = g.Sum(e => e.cena),
IdAuta = g.Key,
Servis = g.Max(e => e.servis)
};
I am not sure which table cena and servis are coming from but to create grouped sum you do something like.
select new { Sum = grouped.Sum( x => x.cena ) }
and to get max
select new { Max = grouped.Group.Max( x => x.servis ) }
Here is a good reference for you.
MSDN - 101 LINQ Samples
I've modified your solution little bit and i got it working like this:
var auta = from jo in
(
from a in MtAuta.FindAll()
join p in DtPoruchy.FindAll() on a equals p.MtAuta into ap
from ap2 in ap.DefaultIfEmpty()
where ap2.SERVIS >= 3
select new
{
Cena = ap2.CENA,
Idauto = ap2.ID_AUTA,
Servis = ap2.SERVIS
}
)
group jo by jo.Idauto into g
select new
{
Cena = g.Sum(jo => jo.Cena),
IdAuto = g.Key,
Servis = g.Max(jo => jo.Servis)
};
I just curious if this is the best solution?

Categories

Resources