LINQ to SQL Grouping and Counting - c#

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.

Related

Linq query for top parents by number of childs, including this number

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);

How to filter LINQ query by table column and get count

I'm trying to get a list of students based on their status, grouped by their college.
So I have three tables, Students and Colleges. Each student record has a status, that can be 'Prospect', 'Accepted' or 'WebApp'. What I need to do is get a list of students based on the status selected and then display the College's name, along with the number of students that go to that college and have their status set to the status passed in. I think this needs to be an aggregate query, since the counts are coming from the string Status field.
I'm not sure how to do this in MS SQL, since the count is coming from the same table and it's based on the status field's value.
Here is the start of my query, which takes in the search parameters, but I can't figure out how to filter on the status to return the counts.
SELECT Colleges.Name, [Status], Count([Status])
FROM Students
JOIN Colleges ON Students.UniversityId = Colleges.id OR Students.+College = Colleges.Name
GROUP BY Students.[Status], Colleges.Name
ORDER BY Colleges.Name;
Accepts = Status('Accepted')
WebApps = Status('WebApp')
Total = Sum(Accpets + WebApps)
Select
Colleges.Name,
SUM(Case when Students.Status like 'Accepted' then 1 else 0 end) Accepts,
SUM(Case when Students.Status like 'WebApp' then 1 else 0 end) WebApps,
COUNT(*) Total
from Students
join Colleges on Students.UniversityId = Colleges.Id OR Students.CurrentCollege = Colleges.Name
Group by Colleges.Name
The LINQ:
var results =
(from c in db.Colleges // db is your DataContext
select new
{
CollegeName = c.Name,
AcceptedStatus = db.Students.Count(r => r.Status.ToUpper() == "ACCEPTED" && (r.UniversityId == c.Id || r.CurrentCollege == c.Name)),
WebAppStatus = db.Students.Count(r => r.Status.ToUpper() == "WEBAPP" && (r.UniversityId== c.Id || r.CurrentCollege == c.Name)),
Total = db.Students.Count(s => s.UniversityId == c.Id || s.CurrentCollege == c.Name)
}).ToList();
Try this http://www.linqpad.net/
Its free and you can convert the linq to sql queries

want to convert SQL query to LINQ query in E.F

I am developing app with MVC 3.5 and EF.
I have written the SQL query and I want to rewrite in the LINQ, but I don't know how to use it...
here is the sql query
select * from PurchaseOrders where CreatedById in
(select Employees_Id from EmployeeRole where Roles_Id in
(select Roles_Id from EmployeeRole where Employees_Id = 17))
Assuming:-
your context is set up correctly and you have all the navigation
properties in place
your query is "Get me all of the purcahse orders
created by any employee who shares a role with employee #17"
You can use:-
context.Employees.Where(x => x.Id == 17)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders);
Assuming that your above query is just a bit weird and you actually meant to do:
SELECT * FROM PurchaseOrders WHERE CreatedById = 17;
Your LINQ query would be:
PurchaseOrders.Where(Order => Order.CreatedById = 17);
or
var Orders = from Order in PurchaseOrders
where Order.CreatedById = 17
select Order;
Seeing your update I guess you would actually be better off selecting you employee and then all of the purchase orders i.e.
var Orders = Employees.Single(x => x.Id == 17).PurchaseOrders;
but beware above will work only if there is such an employee
var s= (from po in _db.PurchaseOrders
join er in _db.EmployeeRoles on po.CreatedById equals er.Employees_Id
let _ser in _db.EmployeeRoles.Where(c=>c.Employees_Id == 17)
where _ser.Select(c=>c.Roles_Id).contails(er.Roles_Id)
Select po).toList();

C# Linq Select two tables select MAX date from one

I have two tables:
User
-----------------
ID int
Name varchar
UserStatus
-----------------
ID int
UserId int
Status varchar
ActiveDate datetime
EndDate datetime
Using Linq in C# how would I get all information from the User table and all the columns from the user status table by the max active date and the end date being null?
I know the following wont work but it is kind of a rudimentary example of what I am trying to do.
ctx.Users.Include("UserStatus").Where(s => s.UserStatus.Max(t => t.ActiveDate) & s.UserStatus.EndDate != null).OrderBy(s => s.Name)
Thanks
EDIT
Lets say the user table has the following:
1 Billy Bob
2 Bilbo baggins
and the user status table has:
1 1 Active 1/1/2011 null
2 1 Reserved 1/1/2011 3/5/2011
3 2 Active 2/22/2011 null
I would like the following results:
1 Billy Bob Active 1/1/2011
2 Bilbo Baggins Active 2/22/2011
Try doing this in two parts. First, group by and set the max value (using the let keyword), then compare using that value and finally select your object.
var query = (from user in ctx.Users
join userStatus in ctx.UserStatuses on user.ID equals userStatus.User.ID
where userStatus.EndDate == null
group userStatus by new
{
userStatus.User.ID,
userStatus.ActiveDate
} into userGroup
let maxActiveDate = userGroup.Max(x => x.ActiveDate)
from userStatus in userGroup
where userStatus.ActiveDate == maxActiveDate
select new
{
userStatus.User.ID,
userStatus.User.Name,
userStatus.Status,
userStatus.ActiveDate
});
You could use something like this:
public IEnumerable<UserStatus> GetUsers(string name)
{
var query = (from u in db.User
join us in db.UserStatus on u.ID equals us.ID
where u.Name == name
orderby us.ActiveDate descending
select us)
as IEnumerable<UserStatus>;
return query;
}
Or, if you only want the single record w/ the MAX ActiveDate, you would keep the same linq statement, but use .First() at the end, and you'd change your return type as well to be only DateTime, etc.
ctx.Users.Where(u => u.UserStatus.Max(us => us.ActiveDate) && u.UserStatus.EndDate.HasValue())
.OrderBy(u => u.Name)
that seems like what you want
If you're looking for every entry that does NOT have an End Date (thus is active), then you could just use
Where(x => x.UserStatus.EndDate == null)
I don't see the need for the max date in your examples.

How to use group by and having count in Linq

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.

Categories