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);
Related
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)
};
I have the following query in SQL which returns 5 rows of data:
SELECT DISTINCT c.Id, c.FirstName, c.LastName, c.PhoneNumber, 'Waiting to be sent'
FROM DistributionGroupMembers dgm
JOIN Contacts c on dgm.ContactId = c.Id
JOIN DistributionGroups dg on dgm.DistributionGroupId = dg.Id
WHERE dg.Id IN (
SELECT DistributionGroupId
FROM DistributionGroupInSms
WHERE SmsId = 40
)
When I try to run the adequate query in C# using LINQ it won't return anything:
int[] groupIDs = await _db.DistributionGroupInSms.Where(dgis => dgis.SmsId == message.Id).Select(g => g.Id).ToArrayAsync();
var recipients = await (from dgm in _db.DistributionGroupMembers
join c in _db.Contacts on dgm.ContactId equals c.Id
join dg in _db.DistributionGroups on dgm.DistributionGroupId equals dg.Id
where groupIDs.Contains(dg.Id)
select new
{
ID = c.Id,
FN = c.FirstName,
LN = c.LastName,
PN = c.PhoneNumber,
SR = "Waiting to be sent"
}).Distinct().ToListAsync();
What am I doing wrong?
Can you simply do a join:
int[] groupIDs = await _db.DistributionGroupInSms.Where(dgis => dgis.SmsId == message.Id).Select(g => g.Id).ToArrayAsync();
var recipients = await (from dgm in _db.DistributionGroupMembers
join c in _db.Contacts on dgm.ContactId equals c.Id
join dg in _db.DistributionGroups on dgm.DistributionGroupId equals dg.Id
join gIds in groupIDs on gIds equals dg.Id
select new
{
ID = c.Id,
FN = c.FirstName,
LN = c.LastName,
PN = c.PhoneNumber,
SR = "Waiting to be sent"
}).Distinct().ToListAsync();
I figured it out, in the select clause by getting the groupIDs I selected Id instead of another field in the table called DistributionGroupId. Thanks everyone for the input
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 have a query in entity framework which gets some messages from tables.
var ur = (from m in en.Messages
join mb in en.aspnet_Membership on m.FromUserId equals mb.UserId
join urs in en.UserProfiles on mb.UserId equals urs.UserId
join g in en.Groups on m.ToUserId equals g.GroupId
join ug in en.UserInGroups on g.GroupId equals ug.GroupId
where ug.UserId == userId
select new
{
InboxId = m.MessageId,
FromUser = urs.RaveName.Trim(),
CreatedOn = m.CreatedOn
}
).Concat(
// msg is not deleted
from m in en.Messages
join mb in en.aspnet_Membership on m.FromUserId equals mb.UserId
join urs in en.UserProfiles on mb.UserId equals urs.UserId
where m.ToUserId == userId
select new
{
InboxId = m.MessageId
,
FromUser = urs.RaveName.Trim()
,
CreatedOn = m.CreatedOn
}
);
I have another table which shows whether the message is used:
var msg = (from m in en.MessagesUsed
where m.UserId == userId
select m
);
Now, I need to check: Is there a message in 'ur' that is not in 'msg'? In T-SQL, we can use:
SELECT 1
FROM ur
WHERE NOT EXISTS (SELECT 1 FROM msg WHERE msg.Id = ur.InboxId AND msg.FromUser = ur.FromUser AND msg.CreatedOn = ur.CreatedOn)
to check this. But how to do it in LINQ?
Thanks
could anybody help me about
"How to select a field that is not in Group By clause in LINQ"
var ReportData =
from a in context.Table1
from b in context.Table2
where a.personelID == b.ID
&& a.DateField.Value.Year == 2011
group a by new { a.personelID, b.Name, b.Surname} into grouping
select new
{
// grouping.Key.DateField,
Name= grouping.Key.Name,
Surname= grouping.Key.Surname,
PagaBruto = grouping.Sum(i => i.Bruto)),
};
I can't select the field "DateField" that is in Table1, I don't want to have this field in Group By, because I will get a wrong result.
THANKS!
I think you need to select both table members before you group by so you can select data from both. I did a join instead of your where clause.
(from a in context.Table1
join b in context.Table2 on a.PersonalID equals b.ID
select new { A=a, B=b } into joined
group joined by new { joined.A.PersonalID, joined.B.Name, joined.B.Surname } into grouped
select grouped.Select(g => new {
DateField= g.A.Datefield,
Name = g.B.Name,
Surname = g.B.Surname,
PagaBruto = g.A.Sum(i => i.Bruto)
})).SelectMany(g => g);
Maybe this will work?
group a by new { a.personelID, b.Name, b.Surname, a.DateField} into grouping
select new
{
DateField = grouping.Key.DateField,
Name= grouping.Key.Name,
Surname= grouping.Key.Surname,
PagaBruto = grouping.Sum(i => i.Bruto)),
};