Php 当连接三个表时,MySQL不返回任何内容。两个表在第三个表中有外键。怎么了?
以下结构和查询非常简单,但我不明白为什么我没有得到任何结果:Php 当连接三个表时,MySQL不返回任何内容。两个表在第三个表中有外键。怎么了?,php,mysql,database,select,join,Php,Mysql,Database,Select,Join,以下结构和查询非常简单,但我不明白为什么我没有得到任何结果: SELECT * FROM `comment` JOIN post ON comment.source_id = post.id JOIN article ON comment.source_id = article.id 下面是一个SQL小提琴: 我有表“文章””、“帖子””和评论(在我的真实数据库中,这是另外一个东西,我只是在这里举个例子)。在“评论”表中,我有外键“源id”,将此评论表与“文章”和“发布”表连接。这是
SELECT * FROM `comment`
JOIN post ON comment.source_id = post.id
JOIN article ON comment.source_id = article.id
下面是一个SQL小提琴:
我有表“文章””、“帖子””和评论(在我的真实数据库中,这是另外一个东西,我只是在这里举个例子)。在“评论”表中,我有外键“源id”,将此评论表与“文章”和“发布”表连接。这是因为文章和帖子的id是唯一的,并且永远不会冲突
我的意思是,如果你看我的提琴示例,你会看到帖子id是2001和2002,而文章id是3001和3002。而且永远不会有id为3001的帖子或id为2001的文章(我知道你们可能认为这会发生,但不会,因为在实际系统中,这些id不是自动递增的)
如您所见,我希望从所有3个表中选择数据,但我什么也没有得到。输出应该类似于:
id source_id text id title
1 2001 First comment 2001 First post
2 2002 Second comment 2002 Second Post
3 3001 Third comment 3001 First article
4 3002 Comment on article 3002 Second article
我做错什么了吗?或者这是不可能的?当您连接到“post”或“article”表时,这些应该是外部连接而不是内部连接。当有帖子和文章都连接到评论时,内部连接起作用
SELECT * FROM `comment`
LEFT JOIN post ON comment.source_id = post.id
LEFT JOIN article ON comment.source_id = article.id
;
编辑。它可以在我的本地副本中工作,但由于SQL FIDLE的错误非常严重,不能只显示空行的结果,我可以给您一个示例,在那里显示这种思维方式实际上是正确的
SELECT
comment.id as comment_id,
source_id,
text,
IF(post.id IS NOT NULL, post.id, 0) as post_id,
IF(post.title IS NOT NULL, post.title, 0) as post_title,
IF(article.id IS NOT NULL, article.id, 0) as article_id,
IF(article.title IS NOT NULL, article.title, 0) as article_title
FROM `comment`
LEFT JOIN post ON comment.source_id = post.id
LEFT JOIN article ON comment.source_id = article.id
;
此外,我建议在此处对选择项进行别名处理,以供以后处理。因此,副本中的最终查询应该是(由于空值,此查询在SQL FIDLE中不起作用):
您的数据库结构意味着一种从
comment
到post
以及从comment
到article
的关系。您需要分别处理这些问题,然后合并这两个问题:
SELECT * FROM `comment`
JOIN post ON comment.source_id = post.id
UNION
SELECT * FROM `comment`
JOIN article ON comment.source_id = article.id
这将在您的示例中起作用,因为联合的每一半的列格式都是兼容的。然而,如果您的实际用例有不同的列,您最好重新设计数据库。您可以采取两种方法:
- 在
表(或任何你想称之为的)上有一个书面作品
列,以确定它是一篇文章还是一篇文章。只有当所有(或至少大多数)列都可以用于所有类型时,这才有效类型
- 或者,如果不同类型的格式不同,可能值得将您的公共字段放入
书面工作
(我称之为公共或集合表),然后在必要时添加“专门”表。这些字段只在文章或帖子中使用,每个书面工作类型都有一个字段。
与指定类型的专家表之间的关系为1:1书面工作
如果可以避免“重复使用”外键,则可以使用外键约束,这将使您对数据的完整性有更高的信心。您当前的设计不可能做到这一点。问题在于,每条评论要么属于一篇文章,要么属于一篇文章,而不是同时属于两篇文章。通过在页面和文章表上执行内部联接,您可以查找附加到这两个表的注释,而这些注释并不存在
这些是典型的一对多关系,您可以通过多种方式重新设计模式以更好地处理它们。例如,对于每个不同的内容类型,您可以添加一个
[content\u type]\u comment
表来将内容映射到注释 这仍然没有返回任何内容。你在fiddle中试过这个吗?在fiddle中它不起作用,但将模式粘贴到我的本地副本,并粘贴了我在这里作为答案提供给你的同一个查询,结果成功了。确实做到了应该做的和你期望的。请试一试。您可能还希望为select中的post.id、artice.id等提供别名,因为以后处理它们时会遇到问题。这不起作用,因为两个左连接将导致单独的id
和title
列;一个用于帖子
,一个用于文章
。对于一组单独的列,halfer的联合方法就可以做到这一点。我可以改变IF列来合并id列和title列(如果其中一个为null,则使用另一个),但是,从长远来看,我认为这样更好,如果我们知道我们实际上是在为一篇文章或一篇文章收集评论,我们就知道,在编程方面,我们需要处理好这两个问题。是的,可以。不管怎么说,这个很容易复制。只需单击链接,写入select1,然后写入selectnull(并将其与本地机器的MySQL进行比较)。它不会在有空值的地方显示任何内容。实际上,我可以感谢对这个bug投了反对票(这就是我编辑评论的原因)。+1代表1:1内容类型表。这意味着您可以摆脱现有的文章和帖子表上笨拙的自动增量。当你发现自己在做这样的事情时,这通常是一个好迹象,你应该仔细看看你的模式。谢谢,这很有效。但我不明白你的意思:你最好为帖子和文章建立一个集合表,然后在必要时添加1:1的专业表。Great@black。我已经更新了我的帖子来解释更多关于专业表的内容。
SELECT * FROM `comment`
JOIN post ON comment.source_id = post.id
UNION
SELECT * FROM `comment`
JOIN article ON comment.source_id = article.id