#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