【问题标题】:MySQL Join Returns too many RowsMySQL Join 返回太多行
【发布时间】:2011-12-01 22:07:01
【问题描述】:

我对 MySQL 比较陌生,这部分让我很困惑。

我正在构建一个简单的博客页面,它将显示一个博客以及与之关联的 cmets。我目前有两个表来处理这些数据:

博客

.blog_id (primary), .blog_title, .blog_date, .blog_post

评论

.comment_id (primary), .blog_id, .comment_name, .comment

我要做的是拉出一个与 ID 匹配的特定博客,然后拉出与该博客相关联的 cmets。这是我的查询:

SELECT * FROM blogs JOIN comments ON blogs.blog_id=comments.blog_id WHERE blogs.blog_id = $active ORDER BY comments.comment_id

此查询会提取正确的信息,但如果博客上有两个 cmets,它将在循环通过 cmets 时显示博客和所有内容两次。我想显示所有博客信息一次,然后让它循环通过 cmets。

我希望我解释清楚了。任何帮助都会很棒。谢谢。

【问题讨论】:

  • 好吧 - 只需存储当前博客的 id 并在下一次迭代时检查它。如果相同 - 不要输出它
  • 把查询分成两步怎么样?第一个您将获得博客数据,第二个您将获得该博客的所有评论。
  • 我希望在一个查询中执行此操作。是否可以尝试构建一个 sub...er..nested 查询?如果是这样,我怎么能在这里使用它?

标签: php mysql inner-join


【解决方案1】:

您所描述的行为是联接应该执行的操作。如果您只希望每个博客条目有 1 条记录,那么您需要使用 group by。要获取包含 cmets 数量的所有博客记录的列表,您可以执行如下查询:

SELECT blogs.*,Count(comments.comment_ID) 
FROM blogs 
LEFT JOIN comments 
ON blogs.blog_id=comments.blog_id WHERE blogs.blog_id = $active 
ORDER BY comments.comment_id
GROUP By Blog.BlogID

但是,您说您只想显示博客,然后显示与该博客关联的 cmets。在这种情况下,您很可能只使用初始查询来拉取所有博客,然后在遍历所有博客条目以获取每个博客的 cmets 时使用另一个查询。这是一些伪代码。

select * FROM blogs

For each record from above
    Code for displaying blog goes here

    Select * FROM Comments where Blog_id = $blogID

    For each comment from above query
        code for displaying comment goes here

    Next COmment

Next Blog

您可以只对所有 cmets 进行一次选择,这会更有效,但会使结果代码更加复杂,因为您必须使用 php 在结果列表中查找记录。只使用多个查询会更简单,而且对于大多数博客(一页最多 10 篇文章)来说,它不会有太大的不同。如果你真的想使用单个查询,你可以像下面的伪代码那样构建你的程序。

SELECT * FROM blogs 
LEFT JOIN comments ON blogs.blog_id=comments.blog_id 
WHERE blogs.blog_id = $active ORDER BY blogs.blog_id, comments.comment_id

$LastBlogID = -1

FOR EACH Record
    If $LastBlogID != record['blog_id']
        Display Blog Information
        $LastBlogID = record['blog_id']
    End If

    Display Comment Information
Next Record

【讨论】:

  • 11 个查询而不是 1 或 2 个 10 项页面 差别很大
  • 11 大于 2,但从执行时间上看,可能不会很明显。
  • 确实不会针对每天 10 个访问者的网站。
【解决方案2】:

有两种方法可以解决这个问题:

如果您绝对需要在一个查询中执行此操作,请使用您连接的 SQL 并使用博客 ID 作为唯一键迭代结果:

$blogId = 0;
while ( null != ($row = mysql_fetch_assoc( $result ) ) )
{
  if ( $row['blog_id'] != $blogId )
  {
     // Display blog contents here
     $blogId = $row['blog_id'];
  }
  // Print coment
}

更有效的方法是将其作为两个查询运行。首先选择博客信息,加上帖子的数量:

SELECT blog_id, blog_title, blog_date, blog_post, COUNT(*) as comment_count
FROM blogs INNER JOIN comments ON blogs.blog_id = comments.blog_id
WHERE blog_id = $blogId
GROUP BY blog_id, blog_title, blog_date, blog_post;

或者,使用子选择:

SELECT blog_id, blog_title, blog_date,
    (SELECT COUNT(*) FROM comments WHERE blog_id = blog.blog_id) as comment_count
FROM blogs
WHERE blog_id = $blogId
  • 仅当 comment_count 大于零时,单独选择 cmets 并显示。

更不用说有不同类型的博客视图;在索引页面上,第二个查询将是您提取博客摘要和每篇文章的 cmets 计数所需的全部内容,而无需显示每条评论的内容。

【讨论】:

    【解决方案3】:

    您需要查看两个部分,一个是您的查询,另一个是您如何显示这些内容。

    我刚刚找到了一些简单的工具来构建 MYSQL 查询并分析您的查询,您甚至可以将您的数据库与网站连接。

    您可以在谷歌浏览器市场中搜索或通过以下链接访问。

    我只是给出一个建议和方向,而不是真正解决它。

    MYSQL query builder

    【讨论】:

      猜你喜欢
      • 2021-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 2018-12-15
      • 1970-01-01
      相关资源
      最近更新 更多