LINQ左连接,group by和Count生成错误的结果

时间:2017-03-09 12:41:35

标签: c# linq

我正在努力与linq(左连接 - 组 - 计数)。请帮我。 下面是我的代码,它给了我这个结果。

Geography       2
Economy         1
Biology         1

我期待着这个...

Geography       2
Economy         1
Biology         0

我该如何解决?

class Department
{
    public int DNO { get; set; }
    public string DeptName { get; set; }
}

class Student
{
    public string Name { get; set; }
    public int DNO { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        List<Department> departments = new List<Department>
        {
            new Department {DNO=1, DeptName="Geography"},
            new Department {DNO=2, DeptName="Economy"},
            new Department {DNO=3, DeptName="Biology"}
        };

        List<Student> students = new List<Student>
        {
            new Student {Name="Peter", DNO=2},
            new Student {Name="Paul", DNO=1},
            new Student {Name="Mary", DNO=1},
        };

        var query = from dp in departments
                    join st in students on dp.DNO equals st.DNO into gst
                    from st2 in gst.DefaultIfEmpty()
                    group st2 by dp.DeptName into g
                    select new
                    {
                        DName = g.Key,
                        Count = g.Count()
                    };

        foreach (var st in query)
        {
            Console.WriteLine("{0} \t{1}", st.DName, st.Count);
        }
    }
}

4 个答案:

答案 0 :(得分:3)

var query = 
            from department in departments
            join student in students on department.DNO equals student.DNO into gst
            select new
            {
                DepartmentName = department.DeptName,
                Count = gst.Count()
            };

我认为回答您的问题不需要任何分组。 你只想知道两件事: - 部门名称 - 每个部门的学生人数

通过使用'join'和'into',您将连接的结果放在临时标识符gst中。您只需要计算gst中的结果数量。

答案 1 :(得分:2)

var query = from dp in departments
            from st in students.Where(stud => stud.DNO == dp.DNO).DefaultIfEmpty()
            group st by dp.DeptName into g
            select new
            {
                DName = g.Key,
                Count = g.Count(x => x!=null)
            };

您希望按部门名称对学生进行分组,但您希望计数过滤掉空学生。我确实略微改变了连接语法,尽管这并不重要。

Here is a working fiddle

答案 2 :(得分:2)

好吧,看看 @Danny 在他的回答中说了什么,这是本案最好,最干净的解决方案。顺便说一句,您也可以将其重写为lambda语法:

    var query = departments.GroupJoin(students,
                   dp => dp.DNO, st => st.DNO,
                   (dept,studs) => new
                       {
                           DName = dept.DNO,
                           Count = studs.Count()
                       });

我发现这种语法在结果中更容易预测,而且通常更短。

顺便说一下:.GroupJoin实际上是一个&#34;左连接&#34;,而且.Join是&#34;内连接&#34;。小心不要误认为一个。

答案 3 :(得分:0)

我的回答类似于@Igor

                    var query = from dp in departments
                    join st in students on dp.DNO equals st.DNO into gst
                    from st2 in gst.DefaultIfEmpty()
                    group st2 by dp.DeptName into g
                    select new
                    {
                        DName = g.Key,
                        Count = g.Count(std => std != null)
                    };

g.Count(std =&gt; std!= null)只是您应该采取的一项更改。