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



我正在尝试使用嵌套的linq查询来查询一个表。我的查询正在工作,但速度太慢。我有将近40万排。这个查询在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#语句编写了这个查询。

对于400K记录,您应该能够将学生ID和部门ID返回到内存列表中。

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

一旦你有了这个列表,你就可以按学生ID分组,并选择那些有多个记录的学生。

  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数据库一次,而不是数十万次。

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

您可以简单地对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()调用就可以解决问题。

相关内容

  • 没有找到相关文章

最新更新