Нужна помощь в размещении LIMIT,OFFSET в этом запросе MySQL

Этот запрос возвращает вопросы/ответы форума и их вложенные комментарии (аналогично парадигме StackOverflow).

    SELECT forum_qa.*,
           user_profiles.*,
           c.*,
           n.pid,
           v.*,
           Ifnull(n.ans_count, 0) AS ans_count
    FROM   forum_qa
           JOIN user_profiles
             ON user_id = forum_qa_author_id
           LEFT JOIN (SELECT *
                      FROM   votes) AS v
             ON forum_qa_id = v.forum_qa_id_fk
           LEFT JOIN (SELECT forum_cm_id,
                             forum_cm_author_id,
                             forum_qa_id_fk,
                             forum_cm_text,
                             forum_cm_timestamp,
                             forum_cm_flag,
                             first_name  AS forum_cm_first_name,
                             last_name   AS forum_cm_last_name,
                             facebook_id AS forum_cm_fb_id,
                             picture     AS forum_cm_picture,
                             moderator   AS forum_cm_moderator
                      FROM   forum_cm
                             JOIN user_profiles
                               ON user_id = forum_cm_author_id) AS c
             ON forum_qa_id = c.forum_qa_id_fk
           LEFT JOIN (SELECT forum_qa_parent_id AS pid,
                             COUNT(*)           AS ans_count
                      FROM   forum_qa
                      WHERE  forum_qa_parent_id IS NOT NULL
                      GROUP  BY forum_qa_parent_id) AS n
             ON forum_qa_id = n.pid
    WHERE  forum_qa_id LIKE "%"
           AND forum_qa_parent_id IS NULL
    ORDER  BY forum_qa_timestamp DESC
            LIMIT  0,3

Я пытаюсь разбить результаты на страницы и столкнулся со следующей проблемой:

Помещая LIMIT в конце запроса, я ограничиваю количество строк total, а не количество вопросов/ответов.

Например, LIMIT 0,3 в последней строке дает мне (qa: вопрос/ответ; cm: комментарий):

forum_qa_id   qa_text   forum_cm_id    cm_text
1             asd
2             wer       4              this is a comment
2             wer       5              this is another comment

вместо

forum_qa_id   qa_text   forum_cm_id    cm_text
1             asd
2             wer       4              this is a comment
2             wer       5              this is another comment
3             zxc       
3             zxc       7              yet another comment

Любые предложения, как изменить мой запрос, чтобы LIMIT 0,3 возвращал не 3 строки, а 3 вопроса, независимо от количества вложенных комментариев?

изменения по предложению @michael

    SELECT qa.*,
           user_profiles.*,
           c.*,
           n.pid,
           v.*,
           Ifnull(n.ans_count, 0) AS ans_count
    FROM   (SELECT * FROM forum_qa LIMIT 0, 3) qa
           JOIN user_profiles
             ON user_id = qa.forum_qa_author_id
           LEFT JOIN (SELECT *
                      FROM   votes) AS v
             ON qa.forum_qa_id = v.forum_qa_id_fk
           LEFT JOIN (SELECT forum_cm_id,
                             forum_cm_author_id,
                             forum_qa_id_fk,
                             forum_cm_text,
                             forum_cm_timestamp,
                             forum_cm_flag,
                             first_name  AS forum_cm_first_name,
                             last_name   AS forum_cm_last_name,
                             facebook_id AS forum_cm_fb_id,
                             picture     AS forum_cm_picture,
                             moderator   AS forum_cm_moderator
                      FROM   forum_cm
                             JOIN user_profiles
                               ON user_id = forum_cm_author_id) AS c
             ON qa.forum_qa_id = c.forum_qa_id_fk
           LEFT JOIN (SELECT forum_qa_parent_id AS pid,
                             COUNT(*)           AS ans_count
                      FROM   forum_qa
                      WHERE  forum_qa_parent_id IS NOT NULL
                      GROUP  BY forum_qa_parent_id) AS n
             ON qa.forum_qa_id = n.pid
    WHERE  qa.forum_qa_id LIKE "%"
           AND qa.forum_qa_parent_id IS NULL
    ORDER  BY qa.forum_qa_timestamp DESC

(НАДЕЕМСЯ) РЕШЕНИЕ

После прочтения здесь

http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/

Я решил проиндексировать поле, которое хотел ORDER BY (forum_qa_type) — как только я это сделал, запрос возвращает правильное количество вопросов.

Спасибо @Michael за помощь. Будет обновляться здесь, если это перестанет работать.


person pepe    schedule 16.10.2011    source источник
comment
Только что заметил, что вы отредактировали это. Сколько строк вы получите, используя только одно соединение с user_profiles?   -  person Michael Berkowski    schedule 16.10.2011
comment
Эй, Майкл, взгляните на новую информацию, которую я разместил в короткой версии. это сбивает с толку.   -  person pepe    schedule 16.10.2011
comment
поместите явный ORDER BY в подзапрос qa: ORDER BY something LIMIT 0,3   -  person Michael Berkowski    schedule 16.10.2011
comment
который возвращает 2 вопроса   -  person pepe    schedule 16.10.2011
comment
А form_qa_author_id никогда не бывает NULL? Кроме того, вытащите оттуда этот LIKE '%' для отладки.   -  person Michael Berkowski    schedule 16.10.2011
comment
ОК - ЕСЛИ Я ЗАКАЗЫВАЮ ПО forum_qa_timestamp (INT), то получаю 2 вопроса, но если ЗАКАЗЫВАЮ ПО forum_qa_type (TINY INT), то получаю 3 вопроса   -  person pepe    schedule 16.10.2011
comment
Я действительно не могу понять это :/   -  person Michael Berkowski    schedule 16.10.2011


Ответы (1)


Предполагая, что forum_qa — это таблица, содержащая вопросы, вы можете поместить ее SELECT * в подзапрос с собственным ограничением. Это, конечно, не проверено, но в принципе должно работать.

SELECT     qa.*,
           user_profiles.*,
           c.*,
           n.pid,
           v.*,
           Ifnull(n.ans_count, 0) AS ans_count
    FROM   (SELECT * FROM forum_qa LIMIT 0, 3) qa 
          JOIN user_profiles
             ON user_profiles.user_id = qa.forum_qa_author_id
           LEFT JOIN (SELECT *.....
           -- etc...

Дополнительные ссылки на имя таблицы forum_qa нужно будет изменить на новый псевдоним qa.

person Michael Berkowski    schedule 16.10.2011
comment
спасибо за совет, но я думаю, что где-то ошибся - я разместил обновленный код в OP - он все еще возвращает 3 строки вместо 3 вопросов - есть идеи, что я делаю неправильно? - person pepe; 16.10.2011
comment
@torr Я не вижу других проблем - у вас есть LEFT JOIN, где это уместно. Я бы предложил удалить другие объединенные таблицы/подзапросы и постепенно добавлять их обратно в отладку. - person Michael Berkowski; 16.10.2011