MySQL select with a count query on another table

2019-05-21 08:25发布

问题:

I have simple article application with three tables:

article 
id, title,  body,   user_id

comment
id, article_id, user_id,    body

user
id, username

On the landing page, I want to show the latest article titles with the author name and total numbers of comments of the article. The main problem is how to get total numbers of comments of the article,I did not get it right. I should get the following output:

title           username    total_comments
article 2       user2           0
article 1       user1           2

In my real application, I added a column in article table for total number of comments to the article. this column is updated when a new comment is added to the system. The problem with this is that the article table is locked when a new comment is added. In my application a lot of comments are added every minutes. So I am trying to avoid locking article table with re-writing the SQL query.

Here is some data for testing:

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'
);

回答1:

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


回答2:

How about something like this, can't test it right now so it might have errors.

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


回答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:

If you try this that it answer?

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 

Or with inner syntax

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