【问题标题】:Combine three SQL queries组合三个 SQL 查询
【发布时间】:2010-11-18 20:02:59
【问题描述】:

我正在尝试为我的论坛索引获取数据。获取所有版块的列表、该版块中的主题数以及该版块中每个主题的帖子数。

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。我已经尝试了几种不同的变体,但都没有奏效。

【问题讨论】:

  • 如果你分别运行每个子查询,它们都会给出结果吗?
  • 如果我删除最后一个 JOIN,它会返回正确的结果和正确的线程数。如果我查询最后一个 JOIN 它会返回每个线程 ID 的正确帖子计数。我想我需要找到一种方法来对每块板的所有这些结果求和

标签: sql forum


【解决方案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.*,将列添加到 SELECT 和 GROUP 或将其用作子查询以连接回 board

【讨论】:

    【解决方案2】:

    尝试加入 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
    

    看看这能不能解决问题。

    【讨论】:

    • 帖子数与每个版块不一致。第一个板与其他板的帖子计数重复。然后其余的板以空帖子计数返回。
    【解决方案3】:

    也许是因为您在子查询中缺少 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 的值。

    【讨论】:

      【解决方案4】:

      我看到的问题是您正在尝试获取 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
      

      在每种情况下,您都会查看父对象并计算子对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-18
        • 1970-01-01
        • 1970-01-01
        • 2016-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多