【问题标题】:MySQL select with a count query on another tableMySQL select 与另一个表上的计数查询
【发布时间】:2023-04-08 16:45:01
【问题描述】:

我有一个包含三个表格的简单文章应用程序:

article 
id, title,  body,   user_id

comment
id, article_id, user_id,    body

user
id, username

在着陆页上,我想显示最新的文章标题以及文章的作者姓名和 cmets 总数。主要问题是如何获得文章的cmets总数,我没有弄对。我应该得到以下输出:

title           username    total_comments
article 2       user2           0
article 1       user1           2

在我的实际应用程序中,我在文章表中添加了一列,用于记录文章中的 cmets 总数。当向系统添加新评论时,此列会更新。这样做的问题是在添加新评论时文章表被锁定。在我的应用程序中,每分钟都会添加很多 cmets。所以我试图通过重写 SQL 查询来避免锁定文章表。

以下是一些测试数据:

CREATE TABLE `article` (
`id` INT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 100 ) NULL ,
`body` LONGTEXT NULL ,
`user_id` INT NULL
) ENGINE = MYISAM ;


CREATE TABLE `comment` (
`id` INT NULL AUTO_INCREMENT PRIMARY KEY ,
`article_id` INT NULL ,
`user_id` INT NULL ,
`body` LONGTEXT NULL
) ENGINE = MYISAM ;

CREATE TABLE `user` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 50 ) NOT NULL
) ENGINE = MYISAM ;


INSERT INTO `test`.`user` (
`id` ,
`username`
)
VALUES (
NULL , 'user1'
), (
NULL , 'user2'
);


INSERT INTO `test`.`article` (
`id` ,
`title` ,
`body` ,
`user_id`
)
VALUES (
NULL , 'article 1', 'body article 1', '1'
), (
NULL , 'article 2', 'body article 2', '2'
);

INSERT INTO `test`.`comment` (
`id` ,
`article_id` ,
`user_id` ,
`body`
)
VALUES (
NULL , '1', '1', 'body comment to article 1'
), (
NULL , '1', '1', 'body comment to article 1'
);

【问题讨论】:

    标签: mysql sql count query-optimization table-locking


    【解决方案1】:

    这样的东西怎么样,现在不能测试,所以它可能有错误。

    SELECT a.title, u.username, COUNT(*) total_comments
    FROM article a
      JOIN user u ON (u.id=a.user_id)
      LEFT OUTER JOIN comment c ON (c.article_id=a.id)
    GROUP BY a.title, u.username
    

    【讨论】:

    • 您将为每对夫妇的标题/用户名获得链接到一篇文章的所有 cmets 的计数,独立于他们的作者不确定它是否回答
    • 来自 OP:“在着陆页上,我想显示最新的文章标题以及文章的作者姓名和文章的 cmets 总数。”。此查询应检索每个文章/文章所有者的 cmets 总数。
    • 谢谢,但是如果文章没有评论,上面的查询不会选择文章。
    【解决方案2】:

    如果你试试这个它会回答吗?

    SELECT a.title AS title, 
                 u.username AS username, 
                 count(c.id) AS total_comments 
     FROM articles a, comments c, users u
     WHERE  a.user_id =u.id
        And a.id=c.articles_id
        And c.user_id = u.id 
    

    或者使用内部语法

    SELECT a.title AS title, 
                 u.username AS username, 
                 count(c.id) AS total_comments 
     FROM articles a 
     INNER JOIN comments c ON c.article_id = a.id 
                                              AND c.user_id=u.id
     INNER JOIN users u ON a.user_id = u.id 
     GROUP BY a.id
    

    【讨论】:

      【解决方案3】:
      SELECT article.title AS title, COUNT(  'comment.id' ) AS total_comment, user.username AS username
      FROM article
      JOIN COMMENT ON comment.article_id = article.id
      JOIN user ON user.id = article.user_id
      GROUP BY article.id
      

      【讨论】:

        【解决方案4】:
        SELECT a.title AS title, u.username AS username, count(c.id) as total_comments FROM articles a
           LEFT JOIN comments c ON c.article_id = a.id
           LEFT JOIN users u ON a.user_id = u.id
        GROUP BY a.id
        

        【讨论】:

        • total_cmets 将包含链接到文章的所有 cmets 的计数
        • 你的答案是正确的,但是查询很慢,因为没有使用索引。我不知道如何为此查询选择正确的索引。谢谢
        • comments.article_idarticles.user_id上添加索引,看看是否有改善
        • @Tudor,我做到了,但同样的问题。
        • 您的表中有多少条记录?这些表是 MyISAM 还是 InnoDB,您的数据库的缓存参数大小是多少?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-28
        相关资源
        最近更新 更多