Reputation: 33
2 tables: User and Alarm
Table:User UserID(int), FullName(varchar)
Table:Alarm AssignedTo(int), Resolved(bool)
Query:
SELECT u.Fullname, COUNT(resolved) as Assigned, SUM(CONVERT(int,Resolved)) as Resolved, COUNT(resolved) - SUM(CONVERT(int,Resolved)) as Unresolved
FROM Alarm i LEFT OUTER JOIN Users u on i.AssignedTo = u.UserID
GROUP BY u.Fullname
Results:
Fullname Assigned Resolved Unresolved
User1 204 4 200
User2 39 9 30
User3 235 200 35
User4 1 0 1
User5 469 69 400
For the life of me I can't figure out how to make this into a Linq query. I am having trouble with the grouping function. I've looked a countless examples and none have my combination of Left Outer join with grouping or they are so complicated that I can't figure out how to make it work with mine. Any help here would be Greatly appreciated!!!
Update: I may not have been clear in what I'm looking for. I am looking for the alarms grouped by the AssignedTo Column which is a userid... Except, I want to replace that userid with the FullName that is located in the users table. Someone had posted and deleted something close except it gave me all users in the user table which is not what I'm looking for..
Update 2: See my answer below
Upvotes: 1
Views: 371
Reputation: 33
I finally figured it out.
This:
var results = alarms.GroupBy(x => x.AssignedTo)
.Join(users, alm => alm.Key , usr => usr.UserID, (alm, usr) => new {
Fullname = usr.FullName,AssignedNum = alm.Count(),
Resolved = alm.Where(t=>t.resolved == true).Select(y => y.resolved).Count(),
Unresolved = alm.Where(t=>t.resolved == false).Select(y => y.resolved).Count() });
Reproduces This:
SELECT u.Fullname, COUNT(resolved) as Assigned, SUM(CONVERT(int,Resolved)) as Resolved,
COUNT(resolved) - SUM(CONVERT(int,Resolved)) as Unresolved
FROM Alarm i LEFT OUTER JOIN Users u on i.AssignedTo = u.UserID
GROUP BY u.Fullname
The result is grouped by the AssignedTo (int) but AssignedTo is not selected. Instead FullName is selected from the joined user table.
Many thanks to everyone that tried to help! I learned a lot from your answers.
For bonus points, how would I write my lamdbda answer in a SQL like syntax?
Upvotes: 1
Reputation: 1421
I guess it is not necessarily to use "Grouping" for this query in Linq because the combination of "LEFT JOIN" + "GROUP BY" changed them over to "INNER JOIN".
var results =
from u in users
join a in alarms on u.UserID equals a.AssignedTo into ua
select new
{
Fullname = u.FullName,
Assigned = ua.Count(),
Resolved = ua.Count(a => a.Resolved),
Unresolved = ua.Count(a => !a.Resolved)
};
foreach (var r in results)
{
Console.WriteLine(r.Fullname + ", " + r.Assigned + ", " + r.Resolved + ", " + r.Unresolved);
}
Upvotes: 0
Reputation: 27861
Assuming that you have the following models:
This is the model for Alarm:
public class Alarm
{
public int id { get; set; }
public int AssignedTo { get; set; }
[ForeignKey("AssignedTo")]
public virtual User User { get; set; }
public bool Resolved { get; set; }
}
This is the model for User:
public class User
{
public int UserID { get; set; }
public string FullName { get; set; }
public virtual ICollection<Alarm> Alarms { get; set; }
public User()
{
Alarms = new HashSet<Alarm>();
}
}
This is the model that will hold the alarm statistics for each user:
public class UserStatistics
{
public string FullName { get; set; }
public int Assigned { get; set; }
public int Resolved { get; set; }
public int Unresolved { get; set; }
}
You can then do the following:
var query = context.Users.Select(
user =>
new UserStatistics
{
FullName = user.FullName,
Assigned = user.Alarms.Count,
Resolved = user.Alarms.Count(alarm => alarm.Resolved),
Unresolved = user.Alarms.Count(alarm => !alarm.Resolved)
});
var result = query.ToList();
By the way, you can also modify the query and remove Unresolved = user.Alarms.Count(alarm => !alarm.Resolved)
, and then make the Unresolved
property a calculated property like this:
public class UserStatistics
{
public string FullName { get; set; }
public int Assigned { get; set; }
public int Resolved { get; set; }
public int Unresolved
{
get { return Assigned - Resolved; }
}
}
This will make the generated SQL query simpler.
Upvotes: 2
Reputation: 1
Try this :
from u in context.User
join a in context.Alarm on u.UserID equals a.AssignedTo into g1
from g2 in g1.DefaultIfEmpty()
group g2 by u.Fullname into grouped
select new { Fullname = grouped.Key, Assigned = grouped.Count(t=>t.Resolved != null), Resolved = grouped.Sum
(t => int.Parse(t.Resolved)), Unresolved = (grouped.Count(t=>t.Resolved != null) - grouped.Sum
(t => int.Parse(t.Resolved)))}
Upvotes: 0