2009-01-23 59 views
6

如果我有一个包含1或NULL的标题列和3位列(f1,f2,f3)的表格,我如何编写LINQ以返回标题和每个包含1的位列?我正在寻找相当于这个SQL查询:多列LINQ COUNT

SELECT title, COUNT(f1), COUNT(f2), COUNT(f3) FROM myTable GROUP BY title 

我正在寻找“最好”的方式来做到这一点。当我查看底层的SQL时,我想到了这个版本的4次下沉,所以它太慢了。

回答

0

下面是我提出的解决方案。请注意,这是接近的@OdeToCode(但在VB语法)提出的解决方案,有一个重要区别:

Dim temp = _ 
    (From t In context.MyTable _ 
    Group t.f1, t.f2, t.f3 By t.title Into g = Group _ 
    Select title, g).ToList 

Dim results = _ 
    From t In temp _ 
    Select t.title, _ 
     f1_count = t.g.Count(Function(x) If(x.f1, False)), _ 
     f2_count = t.g.Count(Function(x) If(x.f2, False)), _ 
     f3_count = t.g.Count(Function(x) If(x.f3, False)) 

第一个查询做了分组,但ToList获取分组数据,从服务器。在这里消除计数可以使生成的SQL语句不会为每个计数生成子SELECT。我在本地查询第二个查询。

这是可行的,因为我知道第一个查询将返回一个可管理的行数。如果它返回数百万行,我可能不得不朝另一个方向前进。

+2

请勿将其用于大型数据集!请不要复制并粘贴到您的应用程序。这个答案应该有一个巨大的警告。 – 2014-12-17 19:38:30

2

我认为这是LINQ跌倒的地方。如果你想高效地使用SQL,如果你想要很好的代码,可以使用LINQ。

由于您已经知道SQL,因此您可以始终直接执行查询。

class TitleCount { 
    public string Title; 
    public int Count1; 
    public int Count2; 
    public int Count3; 
} 

DataContext dc = new DataContext("Connection string to db"); 

IEnumerable<TitleCount> query = dc.ExecuteQuery<TitleCount>(
    @"SELECT title, 
      COUNT(f1) as Count1, 
      COUNT(f2) as Count2, 
      COUNT(f3) as Count3 
     FROM myTable GROUP BY title"); 
4

如果你想坚持到LINQ查询和使用匿名类型,查询可能看起来像:

var query = 
     from r in ctx.myTable 
     group r by r.title into rgroup 
     select new 
     { 
      Title = rgroup.Key, 
      F1Count = rgroup.Count(rg => rg.f1 == true), 
      F2Count = rgroup.Count(rg => rg.f2 == true), 
      F3Count = rgroup.Count(rg => rg.f3 == true) 
     }; 

关键是要认识到,要算真正的字段数(它被映射为一个可为空的bool),你可以用Count操作符和谓词来完成。有关LINQ组运营商的更多信息,请点击:The Standard LINQ Operators

+3

这就是我最初想到的解决方案,但生成的查询使用子选择来生成每个单独的计数。在一个有50万行(没有索引)的表上,这个版本需要7秒,而具有3个COUNT的适当的SQL是即时的。 – gfrizzle 2009-01-26 13:32:52