Вопрос
Итак, я пытаюсь создать простой форум.Это будет список тем в порядке убывания по дате создания темы (если нет ответов) или последнего ответа.Вот структура БД:
форум_тема
идентификатор, имя, адрес электронной почты, тело, дата
forum_reply
идентификатор, адрес электронной почты, тело, дата, идентификатор темы
Сам форум будет состоять из HTML-таблицы со следующими заголовками:
Тема, Последнее изменение, # ответов
Как будет выглядеть запрос или запросы для создания такой структуры?Я думал, что это будет связано с перекрестным соединением, но не уверен...Заранее спасибо.
Решение
Во-первых, мне кажется, что никто на самом деле не отвечает на ваш вопрос, а именно:
Как будет выглядеть запрос или запросы для создания такой структуры?
с требуемой структурой
Тема, 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)).
Другие советы
Примерно так:
select * from forum_topic
inner join forum_reply on forum_topic.id=topc_id
Однако не используйте select *
Это плохая практика :)
И мне не нравится, как ты избегаешь нормализации!Это означает, что я бы предпочел:
Пользователи
- ID пользователя
- Имя
- Электронная почта
Потоки
- Идентификатор потока
- Предмет
- Ответил
- AskedByUserID
- Дата
Ответы
- Идентификатор ответа
- Идентификатор потока
- ID пользователя
- Отвечать
- Дата
Затем выберите тему следующим образом:
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
Это было просто написано в моей голове, но, возможно, вам также придется добавить группу.
Да, вы сможете получить его с помощью такого запроса:
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
«Группировка по» — это волшебство, которое дает нам одну строку для каждой темы с МАКС() и СЧИТАТЬ() функции, предоставляющие нам необходимые агрегированные данные.
(РЕДАКТИРОВАТЬ:Я пропустил тот факт, что тело первого сообщения было в таблице тем, поэтому сообщения без ответов не будут пропущены приведенным выше запросом.У Филипа правильная идея: он предлагает вам нормализовать ваши данные.После нормализации запрос, аналогичный приведенному выше, предоставит вам необходимые данные).
Под «нормализованным» вы подразумеваете, что столбец тела «forum_topic» должен быть удален, а фактическое тело темы должно быть первым ответом?