2010-11-18 136 views
1

我試圖爲我的論壇索引提取數據。獲取所有板的列表,該板中的線程數以及該板中每個線程的帖子數。結合三個SQL查詢

SELECT 
board.*, 
IFNULL(a.thread_count, 0) AS thread_count, 
b.post_count 

FROM 
(SELECT * FROM r_forum_boards ORDER BY position) board 

LEFT OUTER JOIN 
    (SELECT r_forum_threads.board, r_forum_threads.id, 
     COUNT(r_forum_threads.id) AS thread_count 
    FROM r_forum_threads) a 
ON board.id = a.board 

LEFT OUTER JOIN 
(SELECT r_forum_posts.thread_id, COUNT(*) AS post_count 
FROM r_forum_posts) b 
ON b.thread_id = a.id 

問題是,post_count返回NULL。我已經嘗試了幾個不同的變體,但都沒有工作。

+0

如果分別運行每個子查詢,它們都會給出結果嗎? – 2010-11-18 20:06:35

+0

如果我刪除最後一個JOIN,它將返回正確的結果和正確的線程數。如果我查詢最後的JOIN,它會爲每個線程ID返回正確的帖子數。我想我需要找到一種方法來彙總每個板子的所有這些結果 – rcapote 2010-11-18 20:15:44

回答

1

我從IFNULL猜測你的SQL是MySQL風味的。在這種情況下,您可以使用COUNT DISTINCT來簡化事情。

SELECT 
board.id, 
COUNT(DISTINCT r_forum_threads.id) AS thread_count, 
COUNT(r_forum_posts.id) AS post_count 
FROM board 
LEFT OUTER JOIN r_forum_threads ON board.id = r_forum_threads.board 
LEFT OUTER JOIN r_forum_posts ON r_forum_posts.thread_id = r_forum_threads.id 
GROUP BY board.id 
ORDER BY board.position 

取決於你如何實際的board.*需要多少,無論是列添加到選擇和分組或以此作爲一個子查詢加盟回board

0

嘗試把在GROUP子句:

LEFT OUTER JOIN 
(SELECT r_forum_threads.board, r_forum_threads.id, COUNT(r_forum_threads.id) AS thread_count FROM r_forum_threads GROUP BY r_forum_threads.id) a 
ON board.id = a.board 

LEFT OUTER JOIN 
(SELECT r_forum_posts.thread_id, COUNT(*) AS post_count FROM r_forum_posts GROUP BY r_forum_posts.thread_id) b ON b.thread_id = a.id 

看看是否做的伎倆。

+0

帖子數不會與每個板子對齊。第一塊板子與其他板子的帖子數量重複。然後剩下的板子返回空柱子數。 – rcapote 2010-11-18 20:12:36

0

也許是因爲您在子查詢中缺少Group By子句?另外,你不需要第一個子查詢。

Select board... 
    , Coalesce(a.thread_count, 0) AS thread_count 
    , b.post_count 
From r_forum_boards 
    Left Join ( 
       Select r_forum_threads.board 
        , r_forum_threads.id 
        , Count(r_forum_threads.id) AS thread_count 
       From r_forum_threads 
       Group By r_forum_threads.board 
        , r_forum_threads.id 
       ) a 
     On a.board = board.id 

    Left Join (
       Select r_forum_posts.thread_id 
        , Count(*) AS post_count 
       From r_forum_posts 
       Group By r_forum_posts.thread_id 
       ) As b 
     On b.thread_id = a.id 
Order By r_forum_boards.position 

您可能會考慮更改查詢稍微使其更容易測試:

Select board... 
    , Coalesce(a.thread_count, 0) AS thread_count 
    , A.post_count 
From r_forum_boards 
    Left Join ( 
       Select r_forum_threads.board 
        , r_forum_threads.id 
        , Count(r_forum_threads.id) AS thread_count 
        , Posts.post_count 
       From r_forum_threads 
        Left Join (
           Select r_forum_posts.thread_id 
            , Count(*) AS post_count 
           From r_forum_posts 
           Group By r_forum_posts.thread_id 
           ) As Posts 
         On Posts.thread_id = r_forum_threads.Id 
       Group By r_forum_threads.board 
        , r_forum_threads.id 
       ) As A 
    On A.board = board.id 
    Order By r_forum_boards.position 

通過這種方式,您可以運行一個內部查詢,並確保您得到A.結果和B.獲得post_count的值。

0

我看到的問題是,您正在嘗試獲取2個相關但稍有衝突的數據片段,並且可能有2個查詢會爲您提供所需的內容。

您首先需要查詢以獲取每塊電路板上的電路板名稱和線程數。

Select Board.*, GroupThread.threadCount 
    FROM r_forum_boards Board 
    INNER JOIN (Select board_id, count(*) as threadCount from r_forum_threads group by board_id) GroupThread ON Board.board_id = GroupThread.board_id 

其次,爲每個線程,你需要的職位,這是基本相同的方法計算:

Select Thread.*, GroupPosts.postCount 
    FROM r_forum_threads Thread 
    INNER JOIN (Select thread_id, count(*) as postCount from r_forum_posts group by thread_id) GroupPosts ON Thread.board_id = GroupPosts.thread_id 

在每一種情況下,你看父對象,並計數兒童。