在两列上分组并创建两个单独的计数

时间:2015-04-11 22:46:07

标签: c# linq

问题

我们有StudentIdLectureId的表格,我们想知道两件事。

  1. CountStudentId每个StudentId出现多少次。
  2. CountStudentIdLectureId每个StudentId + LectureId对出现多少次。
  3. (2)在下面完成。 (1)不是。

    换句话说,如何在一个查询中统计两个不同的群组?

    另一种思考方式是计算StudentId + LectureId组,并将每个StudentId的计数加起来。

    我们尝试了什么

    StudentId + LectureId上的以下查询组。它会计算StudentId + LectureId组的出现次数。它不会计算StudentId组发生的次数。这就是我们想要的。

    var query = joinTable
        .GroupBy(jt => new { jt.StudentId, jt.LectureId } )
        .Select(g => new {
            StudentId = g.Key.StudentId,
            LectureId = g.Key.LectureId, 
            CountStudentId =  -1, // Count all StudentId (i.e. 10)?
            CountStudentIdLectureId = g.Count()
        });
    

    这是我们目前正在接收的结果。在每一行中,-1值应为10(因为我们将每个JoinTable中的十个StudentId播种到了10,我们还没有实现这一点。

    我们想要实现的结果

    ...但在每种情况下都使用-1代替StudentId LectureId CountStudentId CountStudentLectureId 0 0 -1 3 0 1 -1 3 0 2 -1 3 0 3 -1 1 1 0 -1 2 1 1 -1 3 1 2 -1 3 1 3 -1 2 。**

    CountStudentId

    在这些结果中,我们需要10-1而不是StudentId(后者现在只是一个占位符。)

    这是预期的结果,因为每个10出现CountStudentLectureId次,因为每个StudentId的{​​{1}}总和为10,这只是两种说法相同的方式。

    完整演示代码

    这是full Fiddle code供参考。

    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    public static class Program
    {
        public static void Main()
        {
            var joinTable = SeedJoinTable();
    
            var query = joinTable
                .GroupBy(jt => new { jt.StudentId, jt.LectureId } )
                .Select(g => new {
                    StudentId = g.Key.StudentId,
                    LectureId = g.Key.LectureId, 
                    CountStudentId =  -1, // Count all StudentId (i.e. 10)?
                    CountStudentIdLectureId = g.Count()
                });
    
            // this is just the printing of the results
            Console.WriteLine(
                "StudentId".PadRight(15) +
                "LectureId".PadRight(15) +
                "CountStudentId".PadRight(17) +
                "CountStudentLectureId".PadRight(15));
    
            foreach(var x in query)
            {
                Console.WriteLine(string.Format("{0}{1}{2}{3}", 
                    x.StudentId.ToString().PadRight(15), 
                    x.LectureId.ToString().PadRight(15), 
                    x.CountStudentId.ToString().PadRight(17), 
                    x.CountStudentIdLectureId.ToString().PadRight(15)));
            }
        }
    
        public static List<JoinTable> SeedJoinTable()
        {
            var list = new List<JoinTable>();
            var studentId = 0;
            var lectureId = 0;
    
            // insert 20 records
            for(int i = 0; i < 20; ++i)
            {
                if(i != 0)
                {
                    if(i % 10 == 0) 
                    {   
                        // 10 of each studentId
                        ++studentId;
                        lectureId = 0;
                    }
                    if(i % 3 == 0)
                    {
                        // 3 of each lectureId per student
                        ++lectureId;
                    }
                }
    
                list.Add(new JoinTable() { 
                    StudentId = studentId, 
                    LectureId = lectureId 
                });
            }
            return list;
        }
    
        public class JoinTable
        {
            public int StudentId { get; set; }
            public int LectureId { get; set; }
        }
    }
    

1 个答案:

答案 0 :(得分:2)

这是working DotNotFiddle that produces the results that you want to achieve

您需要按StudentId进行分组,并将值设置为LectureId。这允许您获得studentId和studentIdLectureId对的计数。

        var query = joinTable
        .GroupBy(jt => jt.StudentId, jt => jt.LectureId)
        .Select(x => 
             new {
            StudentId = x.Key,
            CountStudentId = x.Count(),
            LectureIds = x.GroupBy(y => y),
        });

这确实会改变你在最终列表中循环的方式,但会为你提供相同数量的循环相同的数据:

    foreach(var x in query)
    {
        foreach(var lectureId in x.LectureIds)
        {
            Console.WriteLine(string.Format("{0}{1}{2}{3}", 
                x.StudentId.ToString().PadRight(15), 
                lectureId.Key.ToString().PadRight(15), 
                x.CountStudentId.ToString().PadRight(17), 
                lectureId.Count().ToString().PadRight(15)));
        }
    }

如果你想在讲座(讲座名,教授等)中加入任何内容,你可以这样做:

        var query = joinTable
        .GroupBy(jt => jt.StudentId, jt => new {LectureId = jt.LectureId, ProfessorId = jt.ProfessorId})
        .Select(x => 
             new {
            StudentId = x.Key,
            CountStudentId = x.Count(),
            LectureIds = x.GroupBy(y => y),
        });