2011-04-14 100 views
0

此查詢需要一組評論,然後在tblCommentVotes表中統計他們的upvotes和downvotes。Linq可以優化這些子查詢嗎?

目前,它通過select子語句形式的select語句對這些進行計數。如果它在主要查詢中處於某種組中,這會更有效嗎?如果可以的話,任何人都可以告訴我如何做到這一點,因爲我無法弄清楚如何做到這一點。

// Get comments 
var q = (
    from C in db.tblComments 
    where 
     C.CategoryID == Category && 
     C.IdentifierID == Identifier 
    join A in db.tblForumAuthors on C.UserID equals A.Author_ID 
    orderby C.PostDate descending 
    select new 
    { 
     C, 
     A.Username, 
     UpVotes = (from V in db.tblCommentVotes where V.CommentID == C.ID && V.UpVote == true select new { V.ID }).Count(), 
     DownVotes = (from V in db.tblCommentVotes where V.CommentID == C.ID && V.UpVote == false select new { V.ID }).Count() 
    } 
) 
.Skip(ToSkip > 0 ? ToSkip : 0) 
.Take(ToTake > 0 ? ToTake : int.MaxValue); 
+1

你是什麼意思的「優化」?更高效的SQL?更少/更優雅的代碼?如果SQL是你想要的,它可能有助於發佈生成的SQL。 – Brook 2011-04-14 23:17:33

+0

要優化SQL,請查看索引,而不是語言。那麼,你確切的模式是什麼? – 2011-04-14 23:45:29

回答

3

你需要做的是做一個左外連接在查詢表達式的db.tblCommentVotes的,造成可能有可能沒有commentVotes?

當你有這個,你應該能夠執行一個查詢,以獲得您的結果。

這可能是這樣的:

var q = (
    from C in db.tblComments 
    where 
     C.CategoryID == Category && 
     C.IdentifierID == Identifier 
    join A in db.tblForumAuthors on C.UserID equals A.Author_ID 
    // the following two lines are the left outer join thing. 
    join voteTemp in db.tblCommentVotes on voteTemp.CommentID equals C.ID into voteJoin 
    from vote in voteJoin.DefaultIfEmpty() 
    orderby C.PostDate descending 
    group C by new { Comment = C, Username = A.Username } into g 
    select new 
    { 
     g.Key.Comment, 
     g.Key.Username, 
     UpVotes = g.Count(x => x.UpVote), 
     DownVotes = g.Count(x => !x.UpVote) 
    } 
) 
.Skip(ToSkip > 0 ? ToSkip : 0) 
.Take(ToTake > 0 ? ToTake : int.MaxValue); 

這是未經測試,甚至可能沒有編譯,但我想應該是這樣的。

1
db.tblComments.Where(c => c.CategoryID == Category && c.IdentifierID == Identifier) 
       .Join(db.tblForumAuthors, c => c.UserID, a => a.Author_ID, 
        (c, a) => 
        new 
        { 
         CommentID = c, 
         AuthorName = a.UserName, 
         UpVotes = c.Join(db.tblCommentVotes, c => c.CommentID 
                  v => v.CommentID, 
                  (c, v) => v).Count(v => v.UpVote) 
         DownVotes = c.Join(db.tblCommentVotes, c => c.CommentID 
                   v => v.CommentID, 
                   (c, v) => v).Count(v => v.DownVote) 
        }); 
+0

這不會導致選擇n + 1場景嗎?第二次? – 2011-04-14 23:36:18

+0

嗯...是的。你的'GroupBy'更好。 – Femaref 2011-04-14 23:53:26

1

要優化它是最好的首先要衡量。

  • 嘗試,使用類似LinqPad查看生成的SQL
  • 然後使用SQL Server Management Studio中看到的查詢計劃是SQL

或:

  • 嘗試運行代碼並查看SQL跟蹤告訴您發生了什麼

如果沒有數據庫,猜測該Linq是否會導致單個查詢或多個查詢來計算UpVotes和DownVotes是非常困難的(但很有趣)。我的猜想是這樣計算UpVotes和DownVotes可能會非常昂貴 - 它可能會導致每個評論2個附加查詢。