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

#mysql #sql #limit #offset

#mysql #sql #ограничение #смещение

Вопрос:

Этот запрос возвращает вопросы / ответы форума и их вложенные комментарии (аналогично парадигме 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 в конце запроса, я в конечном итоге ограничиваю общее количество строк, а не количество вопросов / ответов.

Например, 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’s

     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 за помощь. Будет обновляться здесь, если это перестанет работать.

Комментарии:

1. Только что заметил, что вы отредактировали это. Сколько строк вы получите, используя только одно соединение user_profiles ?

2. эй, Майкл, взгляни на новую информацию, которую я разместил в разделе «короткая версия». это ошеломляет.

3. поместите явное ORDER BY в qa подзапрос: ORDER BY something LIMIT 0,3

4. это возвращает 2 вопроса

5. И form_qa_author_id никогда не имеет значения NULL? Кроме того, извлеките это LIKE '%' оттуда для отладки.

Ответ №1:

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

 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 .

Комментарии:

1. спасибо за совет, но я думаю, что я где-то облажался — я опубликовал обновленный код в OP — он по-прежнему возвращает 3 строки вместо 3 вопросов — есть идеи, что я делаю не так?

2. @torr Я не вижу никаких других проблем — у вас есть LEFT JOIN s, где это уместно. Я бы предложил удалить другие объединенные таблицы / подзапросы и постепенно добавлять их обратно в debug