I have the following LINQ-to-Entities query for MySQL DB
var data = (from agent in db.User
join agentrole in db.UserRole.DefaultIfEmpty() on agent.Id equals agentrole.UserId
join role in db.Role.DefaultIfEmpty() on agentrole.RoleId equals role.Id
join department in db.Department.DefaultIfEmpty() on role.DepartmentId equals department.Id
join client in db.Client.DefaultIfEmpty() on agent.Id equals client.AssignedUserId
join aggclient in db.AggClient.DefaultIfEmpty() on client.Id equals aggclient.ClientId
group new { agent, department, aggclient} by agent.Id into grp
select new
{
grp.Key,
agentName = grp.Max(a => a.agent.FirstName + " " + a.agent.LastName),
departmentNames = "",
newDepositorsCount = 0,
FTDSum = grp.Sum(a => a.aggclient.FirstDepositAmountEuro),
depcount =grp.Count(a => a.department != null),
aggclientfilter = grp.Where(a => a.aggclient != null && a.aggclient.FirstDepositAmount>0).Sum(a => a.aggclient.FirstDepositAmount)
});
On the current query, the last two operations are not working.
The entity cannot parse count and where operations.
change select clause to :
select new
{
grp.Key,
agentName = grp.agent.Max(a => a.FirstName + " " + a.LastName),
departmentNames = "",
newDepositorsCount = 0,
FTDSum = grp.aggclient.Sum(a => a.FirstDepositAmountEuro),
depcount = grp.department.Count(),
aggclientfilter = grp.aggclient.Where(a => a.FirstDepositAmount>0).Sum(a => a.FirstDepositAmount)
});
I assume that you do not use EF Core 5.x, because it supports filtered count.
Problem that there is no correct translation to SQL of such LINQ query. But there are tricks which can return needed result. Also corrected bad LEFT join.
var data =
from agent in db.User
join agentrole in db.UserRole on agent.Id equals agentrole.UserId into ga
from agentrole in ga.DefaultIfEmpty()
join role in db.Role on agentrole.RoleId equals role.Id into gr
from role in gr.DefaultIfEmpty()
join department in db.Department on role.DepartmentId equals department.Id into dg
from department in dg.DefaultIfEmpty()
join client in db.Client on agent.Id equals client.AssignedUserId
join aggclient in db.AggClient on client.Id equals aggclient.ClientId into acg
from aggclient in acg.DefaultIfEmpty()
group new { agent, department, aggclient} by agent.Id into grp
select new
{
grp.Key,
agentName = grp.Max(a => a.agent.FirstName + " " + a.agent.LastName),
departmentNames = "",
newDepositorsCount = 0,
FTDSum = grp.Sum(a => a.aggclient.FirstDepositAmountEuro),
depcount = grp.Sum(a => a.department != null ? 1 : 0),
aggclientfilter = grp.Sum(a => a.aggclient.FirstDepositAmount > 0 ? a.aggclient.FirstDepositAmount : 0)
};
Related
I have 4 tables (Group, Student, Mark, StudentFile, and want to write my SQL query using LINQ in C#.
Here is my query
SELECT
S.Id,
S.FirstName,
S.LastName,
S.MiddleName,
SUM(M.CountOfPasses) CountOfPasses,
(SELECT SUM(CountOfPassesWithARespectful) FROM StudentFile WHERE StudentId = S.Id) WithARespectful
FROM Student S
LEFT JOIN Mark M ON S.Id = M.StudentId
GROUP BY S.Id, S.FirstName, S.LastName, S.MiddleName
I've already tried something like this:
var students = (from G in context.Group
let v = G.Id
from S in context.Student.Where(x => v == x.GroupId)
from F in context.StudentFile.Where(x => x.StudentId == S.Id).DefaultIfEmpty()
from M in context.Mark.Where(x => x.StudentId == S.Id).DefaultIfEmpty()
group new
{
F.CountOfPassesWithArespectful,
M.CountOfPasses,
S.Id
}
by new
{
S.Id,
S.FirstName,
S.LastName,
S.MiddleName,
S.StartCourse,
G.Name,
S.Alphagroup
} into GSF
select new DTOStudent
{
Id = GSF.Key.Id,
FirstName = GSF.Key.FirstName,
LastName = GSF.Key.LastName,
MiddleName = GSF.Key.MiddleName,
CountOfPasses = (int)GSF.Sum(p=>p.CountOfPasses),
WithRespectful = (int)GSF.Sum(x => x.CountOfPassesWithArespectful),
WithOutRespectful = (int)GSF.Sum(x => x.CountOfPasses) - (int)GSF.Sum(x => x.CountOfPassesWithArespectful),
Course = ClassMethods.GetAgeFromDates((DateTime)GSF.Key.StartCourse).ToString() +
ClassMethods.GetShortGroupName(GSF.Key.Name) + GSF.Key.Alphagroup.ToUpper()
}).Distinct().ToList();
I have the following linq query that works fine, but I am wanting to pull one column (CompanyId) from context.Emps into the results along with the results from context.BillingProfiles. How would I modify the select (select prof) below to include said column?
var query = (from prof in context.BillingProfiles
join emp in context.Emps on prof.ID equals emp.ID
join grp in context.BillingGroups on prof.GroupID equals grp.GroupID
where (prof.EndDate == null) && (grp.System == "sysGrp") && (prof.ID == id)
select prof).Distinct()
.Select(x => new OpId()
{
id = x.ID,
GroupId = x.GroupID,
OpId = x.OpID,
StartDate = x.StartDate,
EndDate = x.EndDate,
AddedOn = x.AddedOn,
AddedBy = x.AddedBy,
RemovedOn = x.RemovedOn,
RemovedBy = x.RemovedBy,
Prodid = x.ProdID,
});
Thanks
Project an anonymous object containing those too:
var query = from prof in context.BillingProfiles
join emp in context.Emps on prof.ID equals emp.ID
join grp in context.BillingGroups on prof.GroupID equals grp.GroupID
where prof.EndDate == null && prof.ID == id && grp.System == "sysGrp"
select new { prof, emp.CompanyId, grp };
I working on an app with a SQLite database, now I want to select information from multiple tables using linq, here it is what I did:
from c in dataContext.Convention
join e in dataContext.Engineer on c.Engineer equals e.Code
join o in dataContext.Owner on c.Owner equals o.Code
join t in dataContext.ProjectType on c.ProjectType equals t.Id
join cs in dataContext.ConventionState on c.State equals cs.Id
join sc in dataContext.SiteControl on c.Code equals sc.CodeCv
join pc in dataContext.PlanControl on c.Code equals pc.CodeCv
join scs in dataContext.SiteState on sc.State equals scs.Id
join pcs in dataContext.PlanState on pc.State equals pcs.Id
join rcs in dataContext.ReceptionState on sc.Reception equals rcs.Id
join b in dataContext.Bill on c.Code equals b.CodeCv
where cs.Abr == "EC"
group new { c, e, o, t, scs, pcs, rcs, b } by new
{ c.Code, c.NumSeq, c.Year, c.TotalAmount, c.Title, e.LastName, e.FirstName, o.Name,
tprjt = t.Abr,
scState = scs.Abr,
pcState = pcs.Abr,
rcState = rcs.Abr
} into cvgrp
select new
{
Code = cvgrp.Key.Code,
N_Seq = cvgrp.Key.NumSeq,
Exercice = cvgrp.Key.Year,
Intitulé = cvgrp.Key.Title,
Ingenieur = cvgrp.Key.LastName + " " + cvgrp.Key.FirstName,
MaitreOuvrage = cvgrp.Key.Name,
TypeProjet = cvgrp.Key.tprjt,
CtrlPlan = cvgrp.Key.pcState,
CtrlChantier = cvgrp.Key.scState,
Reception = cvgrp.Key.rcState,
Montant = cvgrp.Key.TotalAmount,
MontantFacturé = cvgrp.Sum(x => x.b.Amount),
MontantRestant = cvgrp.Key.TotalAmount - cvgrp.Sum(x => x.b.Amount),
MontantCréance = cvgrp.Sum(x => x.b.IsPaid == "False" ? x.b.Amount : 0.0 )
}
It seems working but I really don't understand clearly what I did especially in the group by clause. If I add an into clause after the joins before the group by the identifier will work as a table with all the tables joined ?.
I need some explanation to understand linq more.
Thank you in advance.
using the northwind DB, i have to make a query to get employeename, amount of orders per employee and average price of those orders
this is what the query looks like in SQL
SELECT TOP 10
a.LastName, a.FirstName, amountOfOrders = COUNT(DISTINCT b.OrderID), AveragePricePerOrder = SUM(c.Quantity*c.UnitPrice) /COUNT(DISTINCT b.OrderID)
FROM Employees a join orders b on (a.EmployeeID = b.EmployeeID)
join [Order Details] c on b.OrderID = c.OrderID
Group BY a.EmployeeID, a.LastName, a.FirstName
ORDER BY amountOfOrders Desc
this runs fine but I have to make this in c# and I am a little stuck
So far, I have got this
var query_rx = (from c in ctx.Employees
join or in ctx.Orders on c.EmployeeID equals or.EmployeeID
join ord in ctx.Order_Details on or.OrderID equals ord.OrderID
group c by new
{
c.EmployeeID,
c.LastName,
c.FirstName,
amount = c.Orders.Count
} into c
orderby c.Key.amount descending
select new
{
c.Key.LastName,
c.Key.FirstName,
amountOfOrders = c.Key.amount
}).Take(10);
"edit" I am having trouble working the average in, tried a lot of things but I can't get it to work
"edit" I have changed the query a bit with help from Dohnal's suggestion.
This looks almost exactly like what i want in terms of columns, except that the field lastname and firstname are blank, even with ToString
var query_rx = (from or in ctx.Order_Details
join ord in ctx.Orders on or.OrderID equals ord.OrderID
group or by new
{
ord.EmployeeID
} into c
orderby c.Select(x => x.OrderID).Distinct().Count() descending
select new
{
Lastname = (from emp in ctx.Employees
where c.Key.EmployeeID == emp.EmployeeID
select emp.LastName),
Firstname = (from emp in ctx.Employees
where c.Key.EmployeeID == emp.EmployeeID
select emp.FirstName),
c.Key.EmployeeID,
AmountOfOrders = c.Select(x => x.OrderID).Distinct().Count(),
AveragePricePerOrder = c.Sum(x => x.Quantity * x.UnitPrice) / c.Select(x => x.OrderID).Distinct().Count()
}).Take(10);
Try this query:
var query = (from emp in ctx.Employers
join order in ctx.Orders on emp.EmployeeID equals order.EmployerID
join orderDet in ctx.Order_Details on order.OrderID equals orderDet.OrderID
group new { emp, order, orderDet }
by new { emp.FirstName, emp.LastName, emp.EmployeeID, order.OrderID }
into orderGroup
let a = new
{
orderGroup.Key.EmployeeID,
orderGroup.Key.FirstName,
orderGroup.Key.LastName,
orderGroup.Key.OrderID,
sum1 = orderGroup.Sum(x => x.orderDet.Quantity * x.orderDet.UnitPrice),
}
group a by new { a.FirstName, a.LastName, a.EmployeeID } into empGroup
let a2 = new
{
empGroup.Key.FirstName,
empGroup.Key.LastName,
sum = empGroup.Sum(x => x.sum1),
count = empGroup.Count()
}
orderby a2.count descending
select new
{
a2.FirstName,
a2.LastName,
amountOfOrders = a2.count,
AveragePricePerOrder = a2.sum / a2.count
}).Take(10);
I have the following code and want to return a limited subset of this query in LINQ. The limited subset will take u.ID as an argument to the function and count the number of records associated with u.ID from another table.
So far, this is what I have.
var res = from u in db.Users
where id == u.WorkGroupID && jobCount(u.ID) > 0
select
new
{
ArtistID = u.ID,
ArtistName = u.FirstName + " " + u.LastName
};
How can I modify this query to limit the number of returned records based on a count value associated with each u.ID?
EDIT:
New Query Below. Last line returns to caller a list from the last LINQ query.
var res = from u in db.Users
where id == u.WorkGroupID
select
new
{
// SELF
ArtistID = u.ID,
ArtistName = u.FirstName + " " + u.LastName
};
var res2 = res.ToList<dynamic>();
var res3 = from row in res2.AsEnumerable()
where jobCount(row.ArtistID) > 0
select new
{
row.ArtistName,
row.ArtistID
};
return res3.ToList<dynamic>();
Use a group join:
from u in db.Users
join o in db.Other on u.ID equals o.UserID into grp
where grp.Any()
select new
{
ArtistID = u.ID,
ArtistName = u.FirstName + " " + u.LastName
};