2009-01-23 93 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