【问题标题】:MySQL Simple ForumMySQL简单论坛
【发布时间】:2010-09-29 09:19:05
【问题描述】:

所以我正在尝试建立一个简单的论坛。它将是按主题(如果没有回复)或最新回复日期降序排列的主题列表。这是数据库结构:

论坛主题

id、姓名、电子邮件、正文、日期

forum_reply

id、电子邮件、正文、日期、topic_id

论坛本身将包含一个带有以下标题的 HTML 表格:

主题、上次修改、# 回复

生成这样一个结构的查询会是什么样子?我在想它会涉及交叉连接,但不确定...提前致谢。

【问题讨论】:

  • 提个建议 - 如果您以后想要添加正确的用户登录系统和/或线程回复结构,这将很痛苦。

标签: php sql mysql forum


【解决方案1】:

有点像这样:

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

但是,不要使用select *

这是不好的做法:)

而且我不喜欢你避免标准化的方式!意思是我宁愿:

用户

  • 用户 ID
  • 姓名
  • 电子邮件

线程

  • 线程ID
  • 主题
  • 已答复
  • AskedByUserID
  • 日期

回复

  • 回复ID
  • 线程ID
  • 用户 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

现在这只是我从头顶写的,但您可能还需要添加一些分组依据。

【讨论】:

  • 确实似乎有一些严厉的反对意见。我猜你的情况是因为你的查询实际上并没有返回所需的数据
  • 不知道为什么你被否决了。仅供参考,为了解释简单起见,这些列被命名为:-)
  • 我提供的只是一个如何呈现“更好”论坛的示例,以及如何使用连接的示例,在尝试提供一些可靠的好示例时,投票只是徒劳的。跨度>
  • 我想你想选择论坛主题而不是所有主题的列表,我很抱歉造成误解。为此,您将使用 COUNT 并且必须使用 GROUP BY 子句。
  • 另外,我的回答更像是一个通用的,以显示遵循规范化规则的简化结构。
【解决方案2】:

是的,你应该可以通过这样的查询得到它:

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() 函数为我们提供您需要的聚合数据。

(编辑:我错过了第一篇文章的正文在主题表中,因此上述查询会错过没有回复的帖子。Filip 有正确的想法,建议您对数据进行规范化。一旦规范化,与上述类似的查询将为您提供所需的数据)。

【讨论】:

  • 这很接近,但是使用该查询,如果没有回复,主题将不会出现。
  • 该死,是的,错过了。假设第一篇文章是回复,但由于主题中有正文....
【解决方案3】:

“规范化”的意思是去掉“forum_topic”的body栏目,第一回复应该是实际的topic body?

【讨论】:

  • 您可以在此处阅读更多相关信息:devshed.com/c/a/MySQL/An-Introduction-to-Database-Normalization
  • 规范化基本上意味着当你不需要时不要重复自己。例如,您在多个地方都有“电子邮件”,我宁愿使用用户表来存储它。
  • 对,这确实是一种权衡。磁盘空间与处理器时间。连接可能很昂贵——规范化并不总是万能的。在这种情况下,我需要主题本身包含一个描述字段。如何修改您(或 Paul 的)查询以显示主题,即使没有回复?
  • 不是很多。你只需这样做: select * from Threads inner join Users on Threads。 AskedByUserID=用户ID ;它将加入 Usertable,为您提供有关用户和主题的信息。但是,您也需要加入回复。如果您还想要询问用户信息,我会说两次。
【解决方案4】:

首先,在我看来,实际上没有人回答你的问题,即:

生成这样一个结构的查询会是什么样子?

请求结构为

主题、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)

另外,您的结构 IS 已经标准化。相反的建议是对您想要做什么做出假设,例如,假设您有兴趣在添加到电子邮件地址中跟踪用户名。这是非常合理的,但仍然是一个假设。从规范化的角度来看,使用电子邮件地址作为唯一的用户标识符并没有错。

现在,如果您正在寻找有关如何设置数据库的一般建议,我们可以为您提供很多建议。在规范化之前,我会先不使用潜在的关键字作为对象名称(例如,不要给列名称,如“名称”和“日期”)。

关于 Matt 在没有回复时关于值为 NULL 的评论:使用 COALESCE() 函数将解决该问题。 COALESCE() 返回第一个非 NULL 参数(如果所有参数都为 NULL,则返回 NULL)。所以将 MAX(r.Date) 替换为 MAX(COALESCE(r.Date, t.Date))。

【讨论】:

  • 那里有 99%。现在出现所有主题。现在唯一的问题是当主题没有回复时 LastModified = NULL。有什么想法吗?
  • 如果您有 PK 和电子邮件并且两者都重复,它实际上不会遵循规范化。然后你会有多余的。但这是有争议的,所以让我们保持沉默,只是想指出一些重要的观点并帮助实现目标:)
  • 罗布,你就是那个男人。完美运行。感谢大家的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 2013-11-29
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多