Объединить три SQL-запроса - PullRequest
1 голос
/ 18 ноября 2010

Я пытаюсь получить данные для индекса моего форума. Получение списка всех досок, количества потоков в этой доске и количества сообщений для каждой из этих тем в этой доске.

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. Я пробовал несколько разных вариантов этого, но ни один из них не работает.

Ответы [ 4 ]

1 голос
/ 19 ноября 2010

Я догадываюсь из 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.

0 голосов
/ 19 ноября 2010

Проблема, которую я вижу, состоит в том, что вы пытаетесь получить 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

В каждойВ этих случаях вы смотрите на родительский объект и подсчитываете детей.

0 голосов
/ 18 ноября 2010

Возможно, потому что в ваших подзапросах отсутствует предложение 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 голосов
/ 18 ноября 2010

Попробуйте ввести предложение 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

Посмотрите, поможет ли это.

...