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