【问题标题】:How to join child rows from another table and display main row only once using GROUP BY in MYSQL?如何在 MYSQL 中使用 GROUP BY 连接另一个表中的子行并仅显示一次主行?
【发布时间】:2013-01-25 16:39:04
【问题描述】:

我有一个简单的文章和 cmets 系统,包含以下表格:

文章表:

ID | Writer | Text
 1 | Bob    | good article
 2 | Marley | read this

评论表:

ID | Article_ID | Comment
 1 |      1     |  i love this article
 2 |      1     |  good one
 3 |      2     |  waiting for more

我想选择每篇文章及其下方的 cmets。我使用以下查询:

SELECT * FROM articles LEFT JOIN comments ON articles.ID = comments.Article_id 

预期结果:

Article 1: good article
Comments: 1 - i love this article
          2 - good one

Article 2: read this
Comments: 3 - waiting for more

我得到了什么:

Article 1: good article
Comments: 2 - good one

Article 2: read this
Comments: 3 - waiting for more

那么我如何选择每篇文章及其 cmets,并按 id 降序排列文章,并按 ids 降序排列 cmets?

谢谢

【问题讨论】:

  • 你的查询很好,它应该给你想要的结果,所以问题可能出在 php 代码上
  • 它将显示每条评论的文章...所以文章 1 将显示两次,因为它有 2 个 cmets 等等...谢谢 :)

标签: php mysql sql database join


【解决方案1】:

嗯,

其实你的预期结果和结果都是错误的。你如何处理你的数据?

预期的结果是错误的,因为任何 SQL 查询都会返回一个表作为结果。它不能连续包含另一个表。

您的查询返回以下结果:


第1条:好文章

评论:1 - 我喜欢这篇文章


第1条:好文章

评论:2 - 好一个


第 2 条:阅读本文

评论:3 - 等待更多


Witch 应该足以让您获得页面的相关数据。

但我建议将其拆分为单独的查询,文章通常包含很多您不想在结果中复制的数据。

这样(未经测试的代码):

$articles_sql="SELECT * FROM articles";
$comments_sql="SELECT * FROM comments";

$articles=$db->query($sql).getResults();

$comments=$db->query($sql).getResults();

foreach($articles as &$article){
    $article['comments']=array();
    foreach ($comments as $comment){
        if($article['id']==$commnet['article_id']){
            $article['comments'][]=$comment;
        }
    }
}

希望对您有所帮助!

【讨论】:

  • 我可以通过选择文章的方式并在 while 循环中选择 cmets,但我认为应该有一种方法可以在 1 个查询中做到这一点
  • 您可以执行以下操作: SELECT * FROM 文章;选择 * 从 cmets;而不是在 foreach 循环中将两者结合起来。
  • 或选择文章并在while循环内选择并显示cmets,但没有办法将2个查询组合成1
  • 当然有。您自己向我们展示的查询=)。但这是一个查询效率低于两个查询的无数情况之一。
  • 我只是担心性能...2个查询不会比只做1个查询慢得多吗??
【解决方案2】:

您在 cmets 表中有一对多的关系,所以使用它,并将文章左连接到相应的评论,或者您可以在原始查询上使用 RIGHT JOIN,我相信。

SELECT * FROM comments LEFT JOIN articles ON comments.Article_id = articles.ID

SELECT * FROM articles RIGHT JOIN comments ON articles.ID = comments.Article_id

或者我认为甚至

SELECT * FROM articles JOIN comments ON articles.ID = comments.Article_id 

按文章 id 降序然后评论 id 降序排序,继续:

ORDER BY articles.ID DESC, comments.ID DESC

【讨论】:

  • 抱歉所有这些都不起作用...第一个将显示与我的查询相同的结果(文章 1 将显示两次,因为它有 2 个 cmets)...第二个和第三个将仅显示带有 cmets 的文章,而忽略其他文章...谢谢 :)
  • 每当您执行“选择 *”时,都会选择列出的所有表格中的每一列。我不认为那是你想要的。听起来您想将文章名称堆叠在 cmets 之上,对吗?
  • 我需要选择所有列,包括作者和实际文章以及 cmets 和他们的 ids
  • 我认为您想进行两个单独的查询。你不能用一个查询做你想做的事。
  • 如何结合join和select a.*,b.* from Articles a JOIN (SELECT * from cmets on a.id=b.parent_id) as b
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
相关资源
最近更新 更多