MySQL Simple Forum

Итак, я пытаюсь построить простой форум. Это будет список тем в порядке убывания даты либо темы (если нет ответов), либо последнего ответа. Вот структура БД:

forum_topic

идентификатор, имя, адрес электронной почты, тело, дата

forum_reply

id, email, body, date, topic_id

Сам форум будет состоять из HTML-таблицы со следующими заголовками:

Тема, последнее изменение, # ответов

Как бы выглядел запрос или запросы для создания такой структуры? Я думал, что это будет перекрестное соединение, но не уверен ... Заранее спасибо.


person Matt    schedule 03.01.2009    source источник
comment
Просто небольшой совет - это будет болезненно расширять, если позже вы захотите добавить правильную систему входа в систему и / или структуру ответов с цепочкой.   -  person staticsan    schedule 06.01.2009


Ответы (4)


Во-первых, мне кажется, что noboody действительно отвечает на ваш вопрос:

Как бы выглядел запрос или запросы для создания такой структуры?

с запрошенной структурой

Тема, LastModified, # ответов.

SQL для создания таблицы результатов с этой структурой, учитывая предоставленные вами структуры таблиц, будет:

SELECT t.Id, t.Name AS Topic, 
       MAX(r.Date) AS LastModified, 
       COUNT(*) AS NumReplies
FROM Forum_Topic t
LEFT OUTER JOIN Forum_Reply r ON t.id = r.topic_id
GROUP BY t.Id, t.Name

(извините, это проверено только на SQL Server, поскольку в данный момент у меня нет доступа к MySql)

Кроме того, ваша структура ЕСТЬ уже нормализована. Противоположные предложения основаны на предположениях о том, что вы хотите сделать, например, в предположении, что вы заинтересованы в отслеживании имен пользователей в добавлении к адресам электронной почты. Это вполне разумно, но, тем не менее, является предположением. С точки зрения нормализации, нет ничего плохого в использовании адреса электронной почты в качестве уникального идентификатора пользователя.

Теперь, если вы ищете общие предложения по созданию базы данных, мы можем дать вам МНОГО из них. Перед нормализацией я бы начал с того, что не использовал потенциальные ключевые слова в качестве имен объектов (например, не задавал имена столбцов, такие как «Имя» и «Дата»).

Что касается комментария Мэтта о том, что значение NULL при отсутствии ответов: использование функции COALESCE () исправит это. COALESCE () возвращает первый аргумент, отличный от NULL (или NULL, если все аргументы равны NULL). Поэтому замените MAX (r.Date) на MAX (COALESCE (r.Date, t.Date)).

person Rob3C    schedule 03.01.2009
comment
Это на 99%. Теперь появляются все темы. Единственная проблема сейчас в том, что LastModified = NULL, когда в теме нет ответов. Любые идеи? - person Matt; 04.01.2009
comment
На самом деле он не следует за нормализацией, если у вас есть ПК и электронная почта, и оба они повторяются. Тогда у вас будет дублирование. Но это аргумент, поэтому давайте не будем об этом говорить, просто хотел указать на некоторые важные моменты и помочь в достижении цели :) - person Filip Ekberg; 04.01.2009
comment
Роб, ты мужчина. Прекрасно работает. Спасибо всем за помощь! - person Matt; 04.01.2009

Примерно так:

select * from forum_topic
inner join forum_reply on forum_topic.id=topc_id

Однако не используйте select *

Это плохая практика :)

И мне не нравится, как вы избегаете нормализации! Это означает, что я бы предпочел:

Пользователи

  • Идентификатор пользователя
  • Имя
  • Электронное письмо

Темы

  • ThreadID
  • Предмет
  • Ответил
  • AskedByUserID
  • Дата

Ответы

  • ReplyID
  • ThreadID
  • Идентификатор пользователя
  • Отвечать
  • Дата

Затем выберите такую ​​тему:

select ThreadID, Subject, Answered, AksedByUserID, Date from Threads

И выбрав все подобные ответы

select Answer, Date, Name, Email from Threads
inner join Replies on Threads,ThreaID=Replies.ThreadID
inner join Users on AskedByUserID=UserID 
where Threads.ThreadID=xxx

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

person Filip Ekberg    schedule 03.01.2009
comment
Кажется, действительно происходит резкое голосование против. Я бы предположил, что в вашем случае это потому, что ваш запрос фактически не возвращает требуемые данные - person Paul Dixon; 03.01.2009
comment
Понятия не имею, почему вас проголосовали против. К вашему сведению, столбцы были названы так для простоты объяснения :-) - person Matt; 03.01.2009
comment
То, что я предлагаю, - это всего лишь пример того, как будет представлен лучший форум, и пример того, как использовать объединения, отрицательное голосование просто превосходно, когда я пытаюсь предоставить несколько хороших примеров. - person Filip Ekberg; 03.01.2009
comment
Я подумал, что вы хотите выбрать ветку форума, а не список всех веток, прошу прощения за недоразумение. Для этого вы должны использовать COUNT и использовать предложение GROUP BY. - person Filip Ekberg; 03.01.2009
comment
Также мой ответ является более общим, чтобы показать упрощенную структуру, которая соответствует правилам нормализации. - person Filip Ekberg; 03.01.2009

Да, вы сможете получить его с помощью такого запроса:

SELECT 
  forum_topic.id, 
  forum_topic.name AS Topic,  
  MAX(forum_reply.date) AS Last_Modified, 
  count(*) AS  Replies
FROM forum_topic 
INNER JOIN forum_reply ON (forum_topic.id=forum_reply.topic_id)
GROUP BY forum_topic.id

«Группировать по» - это волшебство, которое дает нам одну строку для каждой темы с MAX () и COUNT (), которые предоставляют нам необходимые агрегированные данные.

(РЕДАКТИРОВАТЬ: я пропустил, что тело первого сообщения было в таблице тем, поэтому сообщения без ответов будут пропущены из-за вышеуказанного запроса. Филип имеет правильную идею, предлагая вам нормализовать свои данные. После нормализации запрос аналогично приведенному выше, вы получите нужные данные).

person Paul Dixon    schedule 03.01.2009
comment
Это близко, но с этим запросом тема не появится, если на нее нет ответов. - person Matt; 03.01.2009
comment
Блин, да пропустил. Предполагается, что первое сообщение было ответом, но, поскольку в теме есть тело .... - person Paul Dixon; 03.01.2009

Под "нормализованным" вы имеете в виду, что столбец тела "forum_topic" должен быть удален, а фактическое тело темы должно быть первым ответом?

person Matt    schedule 03.01.2009
comment
Подробнее об этом можно прочитать здесь: devshed.com / c / a / MySQL / Введение в нормализацию базы данных - person Filip Ekberg; 03.01.2009
comment
Нормализация в основном означает не повторяться, когда в этом нет необходимости. Например, у вас есть электронная почта более чем в одном месте, я бы предпочел использовать таблицу пользователей для ее хранения. - person Filip Ekberg; 03.01.2009
comment
Верно, это действительно компромисс. Дисковое пространство против процессорного времени. Объединение может быть дорогостоящим - нормализация - не всегда главное. В этом случае мне нужно, чтобы сама тема содержала поле описания. Что нужно сделать, чтобы изменить ваш запрос (или запрос Пола), чтобы отображать темы, даже без ответов? - person Matt; 03.01.2009
comment
Не очень много. Вы просто делаете:; выберите * из потоков внутреннего соединения Пользователи в потоках. AskedByUserID = UserID; который присоединится к Usertable, предоставляя вам информацию о пользователях и теме. Однако с ответами вам тоже нужно присоединиться. Дважды я бы сказал, хотите ли вы также запрашивать информацию о пользователе. - person Filip Ekberg; 03.01.2009