How to join these two querys in one?

Asked

Viewed 106 times

2

I have a table that records user reviews in Forum responses in rating, where: 0 = Vote No; 1 = Positive vote; 3 = Vote Annulled

Tabela

If I want to take all votes in response from a single user on a topic I do the following:

SELECT reply_id, rating 
FROM `forum_ratings` 
WHERE topic_id = '4' and user_id = '29'

I have another query that takes all votes and groups by answer id, which in this case is the reply_id field.

SELECT reply_id, 
sum(rating = '1') as likes, 
SUM(rating = '0') as unlikes 
FROM `forum_ratings` 
WHERE topic_id = '4' 
GROUP BY reply_id

I would like to group and at the same time have user X vote in front of the result for each reply_id. If the user has not voted either positive or negative in a response, the number 3 is shown. Something like:

reply_id    likes   unlikes current_user
6            234       12        0
7            122       44        1
8            14         5        3 

1 answer

2


Assuming a user has only one vote per question, you can do it as follows, for example:

SELECT A.reply_id, 
       SUM(case when A.rating = '1' then 1 else 0 end) as likes,
       SUM(case when A.rating = '0' then 1 else 0 end) as unlikes,
       MAX(COALESCE(CurrentUser.rating, 3)) as `current_user`
  FROM forum_ratings A
  LEFT JOIN
  (
    SELECT reply_id, rating FROM forum_ratings WHERE user_id = 29 
  ) AS CurrentUser 
    ON CurrentUser.reply_id = A.reply_id
 WHERE A.topic_id = '4' 
 GROUP BY A.reply_id

The MAX function is used because of the aggregation being done at the response level (reply_id). In this case, if the user with id = 29 has voted in the answer we show which was the vote (1, 2, or 3). Otherwise, we show 3.

I think that this alternative should also produce the expected result (it gave the right result in few tests I’ve done)

SELECT A.reply_id, 
       SUM(CASE WHEN A.rating = '1' THEN 1 ELSE 0 END) as likes,
       SUM(CASE WHEN A.rating = '0' THEN 1 ELSE 0 END) as unlikes,
       MIN(CASE WHEN A.user_id = 29 THEN a.rating ELSE 3 END) as `current_user`
  FROM forum_ratings A
 WHERE A.topic_id = '4' 
 GROUP BY A.reply_id
  • I used your example but the results were not correct.

  • where the user id-1 note was 1 and user id-29’s, the result of the user note 29 was 3

  • If he voted it should be 1 positive or 2 negative, what you proposed in the code is exactly what I want. After grouping have the notes of a single user in each reply_id.

  • In your example, user 29 only has a rating record (3), so I assumed that for all answers should show 3.

  • Yes, in this case you’re right, but when the situation changes, it doesn’t work. Like for example if he voted 1 or 2, it should show 1 or 2, but it’s showing 3.

  • Forgetting the example above. Imagine that there are only two votes in reply_id = 4. user_id_1 voted 1 and user_id_2 voted 2. I want the result with user_id_1 votes, it would have to return "1", but returns 3

  • 1

    I did the test with the first chi and it worked, I just had to change the paarte (bd.forum_ratings) to (forum_ratings); But until then everything right, I will test with more users here.

  • The second alternative with MIN seems to give the same result and is more concise. But I do not have much possibility to test.

  • 1

    I tested it here and everything ok, I will send it to the site kkk. Thank you very much Bruno, you are beast!

  • There’s nothing to be thankful for. :)

  • I’ll test with the second too, think she has better performance?

  • I would say yes. Because it would represent only a direct query in the forum_ratings table. To be sure only seeing the execution plan. But if the table doesn’t have many records, you shouldn’t notice the difference.

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.