SQL - 从表1中获取结果,但计算来自2,3和&的所有匹配结果。 4

时间:2012-03-28 00:37:45

标签: mysql sql join

我正在尝试打印20个在线博客文章的列表,以及每篇文章的评论,照片和视频的数量。他们都共享article_id字段,但不是每篇文章都有评论,照片或视频。

到目前为止我的工作查询(没有计数)

SELECT a.article_id, a.title, a.published, a.description, a.status, ad.firstname, ad.lastname FROM blog_articles AS a
LEFT JOIN admins AS ad ON a.author_id = ad.admin_id *** grabs article author
WHERE a.status = 'Online' ORDER BY a.published DESC LIMIT 0, 20

我的尝试(带计数)

SELECT COUNT(comment_id) AS tot_comments, COUNT(photo_id) AS tot_photos,
COUNT(video_id) AS tot_videos, a.article_id, a.title, a.published, a.description,
a.status, ad.firstname, ad.lastname
FROM blog_articles AS a
LEFT JOIN blog_comments AS ac USING (article_id)
LEFT JOIN photos AS p USING (article_id)
LEFT JOIN videos AS v USING (article_id)
LEFT JOIN admins AS ad ON a.author_id = ad.admin_id
WHERE a.status = 'Online'
GROUP BY a.article_id
ORDER BY a.published DESC LIMIT 0, 20

但这很奇怪。我收到了正确的文章和文字数据,但计算结果是合理的!如果一篇文章真的有18条评论,0张照片和1个视频,我显示的结果显示18条评论,0张照片和18个视频。如果一篇文章有​​0条评论,6张照片和1个视频,我的结果是0条评论,6张照片和6个视频!

我接近它的工作,我的加入知识生锈,我的大脑疼,请有人能让我摆脱痛苦并踢我终点线?我可以看到发生了什么,但我无法解决如何解决它。

这是我想在blog_articles表中为每条记录显示的内容:

文章标题:这是标题| 评论: 42 | 照片: 20 | 视频 2

2 个答案:

答案 0 :(得分:4)

我认为你最好的选择是派生表

SELECT a.title, c.cnt as comments, p.cnt as photos, v.cnt as videos
  FROM blog_articles a
 INNER JOIN admins ad
    ON a.author_id = ad.admin_id
  LEFT OUTER JOIN (
   SELECT article_id, COUNT(comment_id) as cnt
     FROM blog_comments
    GROUP BY article_id) c
    ON a.article_id = c.article_id
  LEFT OUTER JOIN (
   SELECT article_id, COUNT(photo_id) as cnt
     FROM photos
    GROUP BY article_id) p
    ON a.article_id = p.article_id
  LEFT OUTER JOIN (
   SELECT article_id, COUNT(video_id) as cnt
     FROM videos
    GROUP BY article_id) v
    ON a.article_id = v.article_id
 WHERE a.status = 'Online'
GROUP BY a.article_id
ORDER BY a.published DESC LIMIT 0, 20

仅仅因为我无法放手,请查看this SQL Fiddle,其中显示了派生表和计数不同选项的执行计划和时间。两者都提供相同的数据,但在此示例中,派生表为0ms,而计数为1ms。看到这些查询使用一些真实数据执行会很有趣,但根据我的经验,派生表会产生计数不能的性能。

答案 1 :(得分:2)

没试过,但请尝试

SELECT COUNT(comment_id) AS tot_comments, COUNT(photo_id) AS tot_photos,
COUNT(video_id) AS tot_videos, a.article_id, a.title, a.published, a.description,
a.status, ad.firstname, ad.lastname
FROM blog_articles AS a
LEFT JOIN blog_comments AS ac ON ac.article_id = a.article_id
LEFT JOIN photos AS p ON p.article_id = a.article_id
LEFT JOIN videos AS v ON v.article_id = a.article_id
LEFT JOIN admins AS ad ON a.author_id = ad.admin_id
WHERE a.status = 'Online'
GROUP BY a.article_id
ORDER BY a.published DESC LIMIT 0, 20