2013-06-02 3 views
1

Я создаю простой форум. Мне нужно отобразить список с последними темами и рядом с каждой темой последний ответ/сообщение. Что-то вроде:Не возвращать все строки с ЛЕВЫМИ СОЕДИНЕНИЯМИ И НУЖНЫМИ

Topic name:   | Last reply: 
Topic name 1 here | 2013-02-01 by username1 
Topic name 2 here | 2013-01-01 by username2 
etc. 

Дело в том, что Темы и ответы находятся в одной таблице под названием «страницы». В этой таблице есть шаблон поля, который содержит, конечно, ID для шаблонов таблицы.

Так что я просто присоединиться шаблоны и фильтр по Template.name для записи «Форум на тему» ​​

Это будет возвращать все темы. Поскольку мне также нужен был последний ответ для каждой темы, я решил сделать подзапрос с фильтром по одному и тому же шаблону, но теперь для записи «Ответ на форум» и упорядочен по адресу Reply.date DESC и с LIMIT 1, который возвращает последний ответ для Эта тема. Теперь пришло время, чтобы показать мой текущий запрос, который прекрасно работает для Темы, которые содержат по крайней мере 1 ответ:

/*----some fields to return----*/ 
SELECT TopicContent.title, ReplyContent.title, Reply.date, Reply.id, 
(
    /*----subquery to return latest reply id used inside HAVING later on----*/ 
    SELECT Reply.id 
    FROM pages AS Reply 
    INNER JOIN templates AS Template ON Reply.template = Template.id 
    WHERE Reply.parent_id = Topic.id 
    AND Template.name = 'Forum reply' 
    ORDER BY Reply.date DESC 
    LIMIT 1 
) AS reply_id 
FROM pages AS Topic 
INNER JOIN templates AS Template ON Topic.template = Template.id 
INNER JOIN page_content AS TopicContent ON Topic.id = TopicContent.page 
/*----left join used because topic could have zero replies if new----*/ 
LEFT JOIN pages AS Reply ON Topic.id = Reply.parent_id 
LEFT JOIN page_content AS ReplyContent ON Reply.id = ReplyContent.page 
WHERE Template.name = 'Forum topic' 
HAVING Reply.id = reply_id 
/*--------------------------------------------------------------------------------*/ 
/*----HAVING   | returns not all topics but with correct latest reply----*/ 
/*----GROUP BY Topic.id | returns topics correctly but incorrect latest reply-----*/ 

Наиболее важным является то, что в настоящее время, если новая тема представляется не содержит никаких ответов пока нет.

Поэтому, когда я использую HAVING, он возвращает только те темы, которые также содержат хотя бы один ответ. И при использовании GROUP BY он не возвращает последние ответы для тем, которые содержат один или несколько ответов. И для тем, которые не содержат ответов, он возвращает NULL, что хорошо.

Нужно ли мне менять JOINS? Любые идеи для решения этой проблемы. Большое спасибо!

ответ

1

Я бы переместил подзапрос MaxId в предложение from, поскольку способ использования GROUP BY не будет работать для того, что вы пытаетесь сделать. Здесь вы просто присоединяете свой набор результатов к подзапросу, который извлекает ваше поле MaxId.

SELECT 
* 
FROM 
    pages 
    . 
    . 
    . 
    LEFT OUTER JOIN 
    (
    SELECT 
     ReplyId As [MaxId], 
     p.Template 
    FROM 
     Pages p INNER JOIN Templates t ON p.Template = t.Id 
    WHERE 
     TemplateName = 'Forum Reply' 
    ORDER BY ReplyDate LIMIT 1 
    ) a ON a.Template = pages.Template 
WHERE 
    Template.name = 'Forum topic' 

В качестве альтернативы (это одна может дать вам больше, чем один ответ, если несколько первых ответов есть точно такое же время, в этом случае вы можете ограничить результаты)

SELECT 
    * 
FROM 
    pages 
    . 
    . 
    . 
    (SELECT 
     ReplyId As [MaxiId], 
     Template 
    FROM 
     Pages p INNER JOIN 
     Templates t ON p.Template = t.id LEFT OUTER JOIN 
     (SELECT 
     p.Template, 
     MIN(ReplyDate) AS [FirstReplyDate] 
     FROM  
     Pages p INNER JOIN 
     Templates t ON p.Template = t.id 
     WHERE 
     TemplateName = 'Forum Reply' 
     GROUP BY 
     p.Template) b ON b.Template = t.id 
    WHERE 
     p.ReplyDate = b.FirstReplyDate 
    ) a ON a.Template = pages.Template 

В любом случае вы должны двигаться, что первый ответный подзапрос в пункт From

+0

Благодарим вас за ответ. Можете ли вы объяснить, почему вы присоединяетесь к a.TemplateId = pages.TemplateId. Я попытался понять/разобраться, но, похоже, не работает. –

+0

Возможно, потому, что я не совсем понимаю вашу структуру данных, но в вашем подзапросе вы присоединяетесь к таблице страниц в таблице шаблонов в этом столбце (я отредактирую ее, чтобы использовать те же имена, которые вы использовали). Вышесказанное должно дать вам общее решение. – Rick

+0

Привет, бенджлис. Спасибо за вашу помощь. Хотя это не сработало. Я думаю, что это невозможно. Не на наших путях. Вот почему я решил осветить темы и ответы из таблицы страниц. Теперь я создаю темы и ответы на таблицы и меняю свой сценарий. Этот путь, конечно, лучший, и теперь у меня нет пустых полей на моей странице страниц, что тоже отлично. Просто было интересно, можно ли это сделать. –

0

Это еще не ответ, а скорее требуется получить дополнительную информацию с плаката, но поскольку он слишком длинный для комментариев, я отправлю сюда.

Из вашего запроса, я могу сделать вывод, что ваши таблицы выглядеть примерно так

templates(id, name) 
pages(id, parent_id, date, template) 
page_contents(page, title) 

pages сохраняет структуру поста, page_contents сохраняет содержание поста, и template определить, какой тип поста. Я прав?

Вопрос:

  • Что такое значение parent_id, если это тема, а не ответ. Поскольку ответ относится к теме, поэтому parent_id должен быть идентификатором темы. Тем не менее, тема не относится ни к одной теме, так что в основном она должна быть либо 0, либо NULL, правильно?
  • Вы ограничиваете себя этим дизайном базы данных, с моей точки зрения, этот дизайн базы данных не подходит для форума, потому что для извлечения чего-то столь же простого, как это, вы должны Вставить JOIN в кучу таблиц.
+0

Вы правы, как выглядит мой стол. Тема parent_id имеет родительскую страницу, которая в этом случае «Новости и информация». Это родительская страница с шаблоном «Группа форумов». Родитель группы форумов - «Форум». Поэтому значение parent_id темы никогда не 0. Нет. Я не ограничен. Я сделал эту структуру своей собственной, потому что я думал, что это будет удобно, когда у вас будет сайт с несколькими языками. Будет храниться в page_content. Я свободен делать все, что захочу, поэтому я мог бы создавать дополнительные таблицы под названием «темы» и «ответы», но я не уверен, если это возможно. Спасибо за быстрый ответ. –