0

I have three tables:

Table(attribute1, attribute2...);    
---------------------------------
Users(iduser, username)    
Link(idlink, title, userid)    
Comment(idcomment, content, linkid, userid)

How to select: Link title, with corresponding username and number of comments?

I'm currently doing like this:
Q1-Select links (SELECT * FROM `links`)
Q2-Extract usernames from previous query(Q1) - (SELECT username FROM `user` WHERE iduser=Q1.userid
Q3-Extract number of comments from Q1 by id (SELECT COUNT(*) as comments FROM `comment` WHERE linkid='Q1.idlink')

I believe we can do this in much more optimized way. I got idea how to get Link with corresponding username but I got stuck when I need to count comments.

3 Answers 3

4
SELECT iduser, username, Link.title, COUNT(idcomment)
FROM Users
LEFT JOIN Link ON (iduser = userid)
LEFT JOIN Comment ON (linkid = idlink)
GROUP BY iduser, idlink

Note that your Comment table is somewhat badly designed - the 'userid' field is not necessary, and can actually lead to situation where you've got a cross-linked record. e.g. a Comment belonging to user A might could be linked to a Link record belonging to user B.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, this is exactly what I wanted! How Am I supposed to construct comment then? I'm selecting userid from comment later when I'm selecting comments. Do you mean I just need to rename column name?
Depends on your usage. Maybe you only allow ONE of linkid or userid to be set, so a single comment can only ever be attached to a user OR a link, but not both.
I think you have both missed the point here. A comment is made by one user about one link.
Comment is made by user on specific link, user can comment more than once, link is made by user, user can make more links.
Then the linkage should be user->link->comment - one single foreign key pointing back at the immediate "ancestor" table. While there's nothing really WRONG with how you've done it (it saves a step trying to get info on a user who left a comment, by eliminating having to join in the link table), it does allow mis-attribution.
|
1

It is good practice to get into the habit of putting the fields you want into both the SELECT and GROUP BY clauses, that way it won't come as such a shock when you have to use an RDBMS that insists on it.

SELECT
    `l`.`idlink`,
    `l`.`title`,
    `u`.`username`,
    COUNT(`c`,`idcomment`) AS `comment_count`
FROM `links` `l`
INNER JOIN `users` `u`
    ON `l`.`userid` = `u`.`iduser`
LEFT JOIN `comments` `c`
    ON `l`.`idlink` = `c`.`linkid`
GROUP BY
    `l`.`idlink`,
    `l`.`title`,
    `u`.`username`

2 Comments

"It is good practice to get into the habit of putting the fields you want into both the SELECT and GROUP BY clauses, that way it won't come as such a shock when you have to use an RDBMS that insists on it." --- no it is not. None of RDBMS requires to put all the group by columns to the select. You can even select none of the group by fields but go with just SELECT COUNT(*)
Sorry. Poorly worded on my part. What I meant is that columns in the column list should either be in the GROUP BY clause or within some kind of aggregate function.
0
SELECT
    l.idlink
    , l.title
    , l.userid
    , u.iduser
    , u.username
    , c.idcomment
    , c.content

FROM Link AS l
    JOIN Users AS u ON u.iduser=l.userid
    JOIN Comment AS c ON c.linkid=l.idlink

2 Comments

he wants group by u.username and the sum of comments per user
Or does he want the count of comments per link? That is what Q3 would suggest.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.