Sql 在一个查询中从三个表获取数据

Sql 在一个查询中从三个表获取数据,sql,Sql,我试图同时从三个表中检索数据。这些表如下所示: 类别 信息 评论 我试图得到的是1条消息(因为我有一个基于id的WHERE子句3),3个类别(因为有3个类别链接到消息)和2条注释(因为有2条注释链接到消息) 我试图通过usnig以下查询检索数据: SELECT categories.category, messages.id, messages.title, messages.message, comments.count, comments.id as commentid, comments.

我试图同时从三个表中检索数据。这些表如下所示:

类别

信息

评论

我试图得到的是1条消息(因为我有一个基于id的
WHERE
子句
3
),3个类别(因为有3个类别链接到消息)和2条注释(因为有2条注释链接到消息)

我试图通过usnig以下查询检索数据:

SELECT categories.category, messages.id, messages.title, messages.message, comments.count, comments.id as commentid, comments.message as commentmessage
FROM categories
RIGHT JOIN 
  (SELECT id, title, message
  FROM messages WHERE messaged.id = 3) messages
ON messages.id = categories.messageid
LEFT JOIN
  (SELECT count(id), id, message
  FROM comments
  GROUP BY id, message) comments
ON messages.id = comments.messageid
ORDER BY article.id DESC
但是,运行此查询时,我得到6个结果:

category      id  title      message      count  commentid  commentmessage
test          3   the title  the message  1      6          comment 1
test          3   the title  the message  1      5          comment 2
installation  3   the title  the message  1      6          comment 1
installation  3   the title  the message  1      5          comment 2
question      3   the title  the message  1      6          comment 1
question      3   the title  the message  1      5          comment 2
我期望的结果是:

category      id  title      message      count  commentid  commentmessage
test          3   the title  the message  1      6          comment 1
question      3   the title  the message  1      5          comment 2
installation  3   the title  the message  1      null       null

只有三行,我就可以得到所有需要的数据。这可能吗?我做错了吗™?

正如评论中提到的,这里有几个问题

首先,由于您要加入三个表,因此您得到的答案是正确的。1 x 2 x 3行=6行

第二,您的评论聚合实际上并没有聚合任何内容。正如您在结果中所看到的,count始终为1,而我希望您认为两条评论的计数为2。由于您是根据id分组的,因此会对每个唯一id执行计数,该id始终为一个。我想你可能想在messageid上分组

SELECT count(*), messageid
FROM comments
GROUP BY messageid
您需要执行另一个联接或单独的查询来获取注释本身

正如评论中所讨论的,你通常不会以这种方式获得信息;您通常只进行三个查询,因为其中两个关系是一对多关系。如果您的类别很短(并且您使用的是SQL Server),您可以将这些类别压缩到它们自己的列中(即“测试、安装、问题”)。下面是你将如何做到这一点

select id, title, message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories
from @Messages m
where m.id = 3
实际上,有几种方法可以做到这一点,但这既快又脏。然后,您只需要对注释进行一次额外的查询。您只需连接到上一个查询,并按如下方式在两行中获取所有信息

select m.id, title, m.message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories,
        cm.message
from @Messages m
left outer join @Comments cm on m.id = cm.messageid
where m.id = 3
但同样,您可能只想进行额外的查询,以避免重复信息

最后,我想展示您可能希望如何进行评论计数

select m.id, title, m.message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories,
        CommentCount,
        cm.message
from @Messages m
left outer join 
(   
    select messageid, COUNT(*) CommentCount
    from @Comments 
    group by messageid
) rsCommentCount on rsCommentCount.messageid = m.id

什么数据库?此外,发布的查询是否实际运行?您的分组方式不包括消息;我通常认为这会失败。据我所知,一个类别得到了相关的1条消息,而这条消息得到了相关的2条评论。所以,如果你有3个类别,你将得到6条评论,两条评论用于类别(两条评论用于消息)。如果您希望获得与预期输出类似的结果,您应该向我们提供更多信息,并决定选择哪种注释。@BertEvans是的。这将失败。很抱歉,复制/粘贴错误。现在修好了。数据库是Postgresql。你做错了。不能按顺序逐行从两个不同的表中检索结果。在联接表时,始终包括所有可能匹配的组合。您真正需要做的是分别提取类别,而不是通过两个单独的查询提取消息。使用一对多关系,您将获得父数据(消息),然后分别检索类别和注释。也就是说,这是可以做到的;你只是在复制数据。是否要求检索尽可能少的行中的所有信息?+1回答得很好。我可能会建议,如果您想演示SQL查询,请尝试,这是为实现此目的而设计的,并且实际上支持Postgre。因此,查询可能永远存在,也可能不会永远存在。
select id, title, message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories
from @Messages m
where m.id = 3
select m.id, title, m.message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories,
        cm.message
from @Messages m
left outer join @Comments cm on m.id = cm.messageid
where m.id = 3
select m.id, title, m.message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories,
        CommentCount,
        cm.message
from @Messages m
left outer join 
(   
    select messageid, COUNT(*) CommentCount
    from @Comments 
    group by messageid
) rsCommentCount on rsCommentCount.messageid = m.id