I am having trouble trying to convert the following query from SQL to Linq, in particular with the having count and group by parts of the query:
select ProjectID
from ProjectAssociation
where TeamID in ( select TeamID
from [User]
where UserID in (4))
group by ProjectID
having COUNT(TeamID) = (select distinct COUNT(TeamID)
from [User]
where UserID in (4))
Any advice on how to do so would be much appreciated.
var groups = from pa in ProjectAssociation
let teamIds = User.Where(u => u.UserID == 4).Select(u => u.TeamID)
where teamIds.Contains(pa.TeamID)
group pa by pa.ProjectID;
var result = from g in groups
let count = User.Where(u => u.UserID == 4).Select(u => u.TeamID).Distinct().Count()
where g.Count() == count
select g.Key;
Or maybe more optimal:
var teamIds = User.Where(u => u.UserID == 4).Select(u => u.TeamID).AsEnumerable();
var groups = ProjectAssociation.Where(pa => teamIds.Contains(pa.TeamID)
.GroupBy(pa => pa.ProjectID);
var result = from g in groups
let count = teamIds.Distinct().Count()
where g.Count() == count
select g.Key;
By the way, i think that by
select distinct COUNT(TeamID)
you meant:
select COUNT(distinct TeamID)
There is a tool (cheap) that will convert queries like this for you. It's called Linqer. I own a copy and have found that it's able to convert event the most complex of queries. The URL is http://www.sqltolinq.com/
It's not free, but it's pretty inexpensive and has a 30 day trial.
Related
In my model, there are entities Article and Tag in many-to-many relation through table ArticleTag.
I want to select "trending tags" - tags with most articles in last X days, and I want this count too.
Basically, I need help creating EF Linq query equivalent to this SQL query, with ideal result being Dictionary<Tag, int>
SELECT TOP 50
t.Id, t.Name, count(*)
FROM ArticleTag at
JOIN Article a ON a.Id = at.ArticleId
JOIN Tag t ON t.Id = at.TagId
WHERE a.DateCreated > '2019-10-01'
GROUP BY t.Id, t.Name
ORDER BY count(*) DESC
Can this be done without having ArticleTag as DbSet in DbContext (since it is not really an entity, and I dont need it besides this query).
You have to use navigation properties for this query and do not need to know anything about ArticleTag table.
var query =
from a in ctx.Articles
from t in a.Tags
where a.DateCreated > someDate
group t by new { t.Id, t.Name } into g
orderby g.Count() descending
select new
{
g.Key.Id,
g.Key.Name,
Count = g.Count()
};
var result = query
.Take(50)
.ToDictionary(x => new Tag { Id = x.Id, Name = x.Name }, x => x.Count);
I have this SQL query that I need to translate to LINQ.
SELECT p.productId, p.name, COUNT(np.ID) AS 'salesLast70', p.quantity
FROM Products p
LEFT JOIN NOrderProducts np
ON np.product_id = p.productId
WHERE np.date_picked > DATEADD(DAY, -70, getdate())
GROUP BY p.productId, p.name, p.quantity
HAVING COUNT(np.ID) < p.quantity
Right now I have the following LINQ query.
var date70 = DateTime.Now.AddDays(-70).Date;
var almostOutOfStockProducts = from p in db.Products
join np in db.NOrderProducts on p.productId equals np.product_id
where np.date_picked > date70
group np by np.ID into npGrp
where npGrp.Count() < p.quantity
select p;
But p cannot be resolved at the end of the LINQ query at > p.quantity and select p.
I'm sure I am missing something in my LINQ query but I cannot seem to find exactly how to fix it.
EDIT:
I ended up using db.Database.SqlQuery(); with the raw query.
To achieve what you want you have to lift the quantity, name from the product up into the group by. You are doing this in your sql version with the clause GROUP BY p.productId, p.name, p.quantity but you are not doing this in your linq version.
An example would be to do:
var almostOutOfStockProducts = db.Products.Join(db.NOrderProducts, p => p.productId, np => np.product_id, (p, np) => new { p, np })
.Where(x => x.np.date_picked > date70)
.GroupBy(x => new { Quantity = x.p.quantity, Name = x.p.name, ProductId = x.p.productId})
.Where(x => x.Count() < x.Key.Quantity)
.Select(x => new {ProductId = x.Key.ProductId, Quantity = x.Key.Quantity, Name = x.Key.Name});
In the GroupBy I am bringing through the product id, quantity and name from the product into an anonymous type. This then becomes the key so I can use it in the Where clause and also in the Select at the end.
I'm having problem coding my linq query.
This is my SQL query:
select
price, (cast(sum(Quantity) as decimal(7,2)))
from
OrderDetails
where
ItemID = 1000
group by
price
order by
price
This is my linq query:
var result = from od in db.OrderDetails
where od.ItemID == 1000
orderby od.Price
group by price
select od.price, (cast(sum(od.Quantity) as decimal(7, 2)));
This linq query seems to be incorrect. What is the right syntax?
This should work:
(You need to move the order part to be after the grouping)
var q = (from o in context.OrderDetails
where o.ItemID == 1000
group o by o.price into grp
select new
{
Price = grp.Key,
Quantity = grp.Sum(x => x.Quantity)
}).OrderBy(a => a.Price);
I have an existing SQL query:
select
mn.accountid, sum(u.peak), sum(u.text), sum(u.datagig),
sum(p.minutesallowed), sum(p.messagesallowed), sum(p.dataallowed)
from
usage u
inner join
mtn mn on u.mtnid = mn.Id
inner join
[plan] p on p.id = mn.planid
group by
mn.accountid
Using Entity Framework, I'm working on converting this to linq, and I've gotten this far:
var tots = from u in currentUsage
join mn in mtns on u.mtnId equals mn.Id
join p in plans on mn.PlanId equals p.Id
group u by u.AccountId into g
select new MainUsageResults
{
TotalPeakMinutes = g.Sum(x => x.Peak),
TotalData = g.Sum(x => x.DataGig),
TotalMessaging = g.Sum(x => x.Text),
TotalAllowedMinutes = g.Sum(x => ???) ,
TotalAllowedMessages = g.Sum(x => ???) ,
TotalAllowedData = g.Sum(x => ???)
};
I can't figure out how to sum up the data that is on the joined tables. In SQL one would have the whole set of columns available in a join, but it doesn't seem to be the case here. How do I get the sum of the columns on the joined tables in this example?
Thanks to #3-14159265358979323846264, a real nice example can be found here
I have searched for solution, but nothing similar.
My problem is that I want to select data from database, group it by UserID and Count it by Status id
Users
UserID
Name
Appointments
UserID
ClientID
Status
StartDate
Status can be active=1, canceled=2, done=3
This is how I will display results.
Thanks in advance.
In you question you say you want to group on UserId, but in the output you show Name. This query will group on both. You might want to adjust it to your needs.
from u in tblUsers
join a in tblAppointments on u.UserID equals a.UserID
group a by new { u.UserID, u.Name } into g
select new
{
Name = g.Key.Name,
Active = g.Count (x => x.Status == 1),
Canceled = g.Count (x => x.Status == 2),
Done = g.Count (x => x.Status == 3)
}
(this will handle the case if two users have the same name though)
This covers grouping operators. This covers the count.