简体   繁体   English

将简单的Left Outer Join和group by SQL语句转换为Linq

[英]Convert simple Left Outer Join and group by SQL statement into Linq

2 tables: User and Alarm 2个表:用户和警报

Table:User UserID(int), FullName(varchar) 表:用户 UserID(int),FullName(varchar)

Table:Alarm AssignedTo(int), Resolved(bool) 表:Alarm AssignedTo(int),已解决(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. 对于我的生活,我无法弄清楚如何将其变成Linq查询。 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. 我正在寻找由AssignedTo列分组的警报,这是一个用户ID ...除了,我想用user表中的FullName替换该用户ID。 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 更新2:请参阅下面的答案

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: 顺便说一句,您还可以修改查询并删除Unresolved = user.Alarms.Count(alarm => !alarm.Resolved) ,然后将Unresolved属性设置为如下计算属性:

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. 这将使生成的SQL查询更简单。

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. 结果按AssignedTo(int)分组,但未选择AssignedTo。 Instead FullName is selected from the joined user table. 而是从连接的用户表中选择FullName。

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? 对于奖励积分,我如何用SQL语法编写我的lamdbda答案?

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

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". 我想在Linq中不一定要对此查询使用“分组”,因为“LEFT JOIN”+“GROUP BY”的组合将它们更改为“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);
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM