3

My tables:

suggestions:
suggestion_id|title|description|user_id|status|created_time

suggestion_comments:
scomment_id|text|user_id|suggestion_id

suggestion_votes:
user_id|suggestion_id|value

Where value is the number of points assigned to a vote.

I'd like to be able to SELECT: suggestion_id, title, the number of comments and the SUM of values for that suggestion. sorted by SUM of values. LIMIT 30

Any ideas?

2
  • use JOIN and aggregate functions SUM() and COUNT() Commented Jun 29, 2010 at 9:49
  • I was thinking that, but I'm not sure what to SUM() and COUNT() Commented Jun 29, 2010 at 9:51

2 Answers 2

2

You may want to try using sub queries, as follows:

SELECT  s.suggestion_id,
        (   
           SELECT COUNT(*) 
           FROM suggestion_comments sc 
           WHERE sc.suggestion_id = s.suggestion_id
        ) num_of_comments,
        (   
           SELECT SUM(sv.value) 
           FROM suggestion_votes sv
           WHERE sv.suggestion_id = s.suggestion_id
        ) sum_of_values
FROM    suggestions s;

Test case:

CREATE TABLE suggestions (suggestion_id int);
CREATE TABLE suggestion_comments (scomment_id int, suggestion_id int);
CREATE TABLE suggestion_votes (user_id int, suggestion_id int, value int);

INSERT INTO suggestions VALUES (1);
INSERT INTO suggestions VALUES (2);
INSERT INTO suggestions VALUES (3);

INSERT INTO suggestion_comments VALUES (1, 1);
INSERT INTO suggestion_comments VALUES (2, 1);
INSERT INTO suggestion_comments VALUES (3, 2);
INSERT INTO suggestion_comments VALUES (4, 2);
INSERT INTO suggestion_comments VALUES (5, 2);
INSERT INTO suggestion_comments VALUES (6, 3);

INSERT INTO suggestion_votes VALUES (1, 1, 3);
INSERT INTO suggestion_votes VALUES (2, 1, 5);
INSERT INTO suggestion_votes VALUES (3, 1, 1);
INSERT INTO suggestion_votes VALUES (1, 2, 4);
INSERT INTO suggestion_votes VALUES (2, 2, 2);
INSERT INTO suggestion_votes VALUES (1, 3, 5);

Result:

+---------------+-----------------+---------------+
| suggestion_id | num_of_comments | sum_of_values |
+---------------+-----------------+---------------+
|             1 |               2 |             9 |
|             2 |               3 |             6 |
|             3 |               1 |             5 |
+---------------+-----------------+---------------+
3 rows in set (0.00 sec)

UPDATE: @Naktibalda's solution is an alternative solution that avoids sub queries.

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

4 Comments

Is there a way not to use sub queries? I just heard their slower.
Yes, you are right, 2 subqueries are executed for each suggestion so thats rather slow.
@Steven, @Naktibalda: In general this won't be slow if the suggestion_id of each table is properly indexed, (and as long as the query won't return many suggestions)... In addition, it can get quite complicated to do multiple aggregations on a single result set.
After testing you seem corrent, and your solution is easier to read
2

I was typing the same query as potatopeelings.
But there is an issue:
Resultset after joins contains M*N rows (M-number of comments, N-number of votes, not less than 1) for each suggestion.

To avoid that you have to count distinct comment ids and divide a sum of votes by number of comments.

SELECT 
    s.*, 
    COUNT(DISTINCT c.scommentid) AS comment_count,
    SUM(v.value)/GREATEST(COUNT(DISTINCT c.scommentid), 1) AS total_votes
FROM suggestions AS s
LEFT JOIN suggestion_comments AS c ON s.suggestion_id = c.suggestion_id 
LEFT JOIN suggestion_votes AS v ON s.suggestion_id = v.suggestion_id
GROUP BY s.suggestion_id
ORDER BY total_votes DESC
LIMIT 30

2 Comments

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 1) AS total_votes FROM suggestions AS s LEFT JOIN suggestion_comments AS c ON' at line 4
Oh, I had to use GREATEST() instead of MAX()

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.