Reputation: 11
I have the following two tables:
content:
| id | name | created_by |
+----+-------+------------+
| 1 | test | me |
| 2 | test2 | me |
| 3 | test3 | you |
| 4 | test4 | me |
like_dislike:
| id | content_id | like | dislike |
+----+------------+------+---------+
| 1 | 1 | 1 | 0 |
| 2 | 2 | 1 | 0 |
| 3 | 2 | 0 | 0 |
I need to calculate the average likes of the last 2 content rows where created_by = me
.
So for example, the last two content_ids are 2 and 4.
The like_dislike table has records for content_id 2, with a row where like is 1 and a row where like is 0, so the average is 1/2.
I have tried the following query but it will not work:
SELECT ((SELECT COUNT(*)
FROM `like_dislike`
WHERE `like`='1' AND `content_id`= pi.id) / (COUNT(*))
FROM content AS pi
WHERE pi.create_by = 'me'
ORDER BY pi.id DESC
LIMIT 2
Upvotes: 1
Views: 1923
Reputation: 1269503
If you only want this information for one user at a time, then you don't need to do fancy things with self joins or variables. You can just use limit
in a subquery:
select avg(like)
from like_dislike ld join
(select c.*
from content c
where c.create_by = 'me'
order by id
limit 2
) c2
on ld.content_id = c2.id;
Upvotes: 0
Reputation: 33935
SELECT x.*
, AVG(liked)
FROM content x
JOIN content y
ON y.created_by = x.created_by
AND y.id >= x.id
JOIN like_dislike z
ON z.content_id = x.id
WHERE x.created_by = 'me'
GROUP BY x.id
HAVING COUNT(DISTINCT y.id) <= 2;
or something like that
Upvotes: 1
Reputation: 16691
It seems like what you're trying to do here also, even though you might not see it, is getting the greatest-n-per-group. See this article for more information.
So, what I would do is start by getting the latest two content
rows that are created by you, like so:
SELECT c.*
FROM content c
WHERE(
SELECT COUNT(*)
FROM content co
WHERE co.created_by = c.created_by AND co.id >= c.id) <= 2
AND c.created_by = 'me';
The next part I will step through a little slower because it is kind of tricky. You can join the above with the like_dislike table on the condition that the content_id matches, so you can view the total likes for each of your last two posts:
SELECT c.*, ld.*
FROM content c
JOIN like_dislike ld ON ld.content_id = c.id
WHERE(
SELECT COUNT(*)
FROM content co
WHERE co.created_by = c.created_by AND co.id >= c.id) <= 2
AND c.created_by = 'me';
Once you have that, you can use the AVG()
function to get the average likes, and group by each content_id, like this:
SELECT c.id, AVG(ld.liked) AS averageLikes
FROM content c
JOIN like_dislike ld ON ld.content_id = c.id
WHERE(
SELECT COUNT(*)
FROM content co
WHERE co.created_by = c.created_by AND co.id >= c.id) <= 2
AND c.created_by = 'me'
GROUP BY c.id;
One important thing to note here: This will only show the post that has activity associated with it. In other words, content_id 4 will not appear. If you need to see it, you can do a LEFT JOIN, and check if the average is null and replace it with 0 if it is, like this:
SELECT c.id, IFNULL(AVG(ld.liked), 0) AS averageLikes
FROM content c
LEFT JOIN like_dislike ld ON ld.content_id = c.id
WHERE(
SELECT COUNT(*)
FROM content co
WHERE co.created_by = c.created_by AND co.id >= c.id) <= 2
AND c.created_by = 'me'
GROUP BY c.id;
And here is your SQL Fiddle.
ALSO NOTE like
is a reserved word in MySQL, so I changed the two columns in the fiddle to be liked
and disliked
. I recommend you do the same.
Upvotes: 0