有没有更快的方法来处理嵌套的 linq 查询?

is there a faster way to work with nested linq query?

我正在尝试使用嵌套 linq 查询来查询 table。我的查询有效但速度太慢。我有将近 400k 行。这个查询对 1000 行工作 10 秒。对于 400k 我认为大约需要 2 个小时。

我有这样的行

StudentNumber - DepartmentID
n100 - 1
n100 - 1
n105 - 1    
n105 - 2
n107 - 1

我想要不同部门ID的学生。我的结果是这样的。

StudentID - List
n105 - 1 2

我的查询提供了它。但慢慢地。

var sorgu = (from yok in YOKAktarim
    group yok by yok.StudentID into g
    select new {
        g.Key,
        liste=(from birim in YOKAktarim where birim.StudentID == g.Key select new { birim.DepartmentID }).ToList().GroupBy (x => x.DepartmentID).Count()>1 ? (from birim in YOKAktarim where birim.StudentID == g.Key select new { birim.DepartmentID }).GroupBy(x => x.DepartmentID).Select(x => x.Key).ToList() : null,
    }).Take(1000).ToList();


Console.WriteLine(sorgu.Where (s => s.liste != null).OrderBy (s => s.Key));

我用 linqpad C# 语句编写了这个查询。

您正在迭代源集合 (YOKAktarim) 三次,这使得您的查询成为 *O(n^3)` 查询。会很慢。

您可以简单地遍历 g.

而不是返回源集合来获取组的内容
var sorgu = (from yok in YOKAktarim
    group yok by yok.StudentID into g
    select new {
        g.Key,
        liste = from birim in g select new { birim.DepartmentID }).ToList().GroupBy (x => x.DepartmentID).Count()>1 ? (from birim in g select new { birim.DepartmentID }).GroupBy(x => x.DepartmentID).Select(x => x.Key).ToList() : null,
    }).Take(1000).ToList();

但是,这仍然不是最佳选择,因为您正在进行大量冗余子分组。您的查询几乎等同于:

from yok in YOKAktarim
group yok by yok.StudentID into g
let departments = g.Select(g => g.DepartmentID).Distinct().ToList()
where departments.Count() > 1
select new {
    g.Key,
    liste = departments
}).Take(1000).ToList();

我不能说那个怪物的正确性,但只需删除除最外层调用之外的所有 ToList() 调用即可解决您的问题。

对于 400K 条记录,您应该能够return将学生 ID 和部门 ID 放入内存列表中。

 var list1 = (from r in YOKAktarim  
            group r by new { r.StudentID, r.DepartmentID} into g  
            select g.Key
           ).ToList();

获得此列表后,您应该可以按学生 ID 和 select 拥有多个记录的学生进行分组。

  var list2 = (from r in list1 group r by r.StudentID into g 
               where g.Count() > 1 
               select new 
                  { 
                      StudentID = g.Key, 
                      Departments = g.Select(a => a.DepartmentID).ToList()
                  }  
               ).ToList();

这应该会更快,因为它只访问 sql 数据库一次,而不是数十万次。