Multi Join + Groub By, get 1 row per album with max rating - mysql

im trying to make a chart list and i use the following query
SELECT
vmm_user.username,
vmm_songs.*,
vmm_albums.desc,
vmm_albums.release,
vmm_albums.name,
AVG(vmm_songrating.rating) AS ratingavg,
COUNT(vmm_songrating.id) AS ratingcount
FROM
vmm_songs
LEFT JOIN
vmm_user
ON
vmm_songs.userid=vmm_user.id
LEFT JOIN
vmm_albums
ON
vmm_songs.albumid=vmm_albums.id
LEFT JOIN
vmm_songrating
ON
vmm_songs.id=vmm_songrating.songid
GROUP BY
vmm_songs.id
HAVING
COUNT(vmm_songrating.id) >= 2
ORDER BY
AVG(vmm_songrating.rating) DESC
LIMIT
10
As you can see i get every entry with at least 2 ratings but i only want to show the songs with the max average rating and minimum 2 ratings per album
i tried to add something like
MAX(AVG(vmm_songrating.rating))
in the having clause but it didnt work
i use php and mysql
Thanks for helping
EDIT 3:
mysql fiddle
http://sqlfiddle.com/#!2/677cf/1/0
just want the first 3 rows (song with highest rating from the album)

Try something like below..
SELECT MAX(songs.ratingavg), [Other Columns]
FROM (
SELECT
vmm_user.username,
vmm_songs.*,
vmm_albums.desc,
vmm_albums.release,
vmm_albums.name,
AVG(vmm_songrating.rating) AS ratingavg,
COUNT(vmm_songrating.id) AS ratingcount
FROM
vmm_songs
LEFT JOIN
vmm_user
ON
vmm_songs.userid=vmm_user.id
LEFT JOIN
vmm_albums
ON
vmm_songs.albumid=vmm_albums.id
LEFT JOIN
vmm_songrating
ON
vmm_songs.id=vmm_songrating.songid
GROUP BY
vmm_songs.id
HAVING
COUNT(vmm_songrating.id) >= 2
ORDER BY
AVG(vmm_songrating.rating) DESC
LIMIT
10 ) AS songs

Related

Searching and Sorting Using MySQL Inner Join

I guess I can't explain my problem properly. I want to explain this to you with a picture.
Picture 1
In the first picture you can see the hashtags in the trend section. These hashtags are searched for the highest total and it is checked whether the date has passed. If valid data is available, the first 5 hashtags are taken.
Picture 2
In the second picture, it is checked whether the posts in the hashtag are in the post, if any, the oldest date value is taken, LIMIT is set to 1 and the id value from the oyuncular table is matched with sid. Thus, the name of the person sharing can be accessed.
Picture 3
My English is a little bad, I hope I could explain it properly.
SELECT
social_trend.hashtag,
social_trend.total,
social_trend.tarih,
social_post.sid,
social_post.tarih,
social_post.post,
oyuncular.id,
oyuncular.isim
FROM
social_trend
INNER JOIN
social_post
ON
social_post.post LIKE '%social_trend.hashtag%' ORDER BY social_post.tarih LIMIT 1
INNER JOIN
oyuncular
ON
oyuncular.id = social_post.sid
WHERE
social_trend.tarih > UNIX_TIMESTAMP() ORDER BY social_trend.total DESC LIMIT 5
YOu should use a sibquery
and add a proper join between subqiery and social_trend
(i assumed sing both sid)
SELECT
social_trend.hashtag,
social_trend.total,
social_trend.tarih,
t.sid,
t.tarih,
t.post,
oyuncular.id,
oyuncular.isim
FROM (
select social_post.*
from social_post
INNER JOIN social_trend ON social_post.post LIKE concat('%',social_trend.hashtag,'%' )
ORDER BY social_post.tarih LIMIT 1
) t
INNER JOIN social_trend ON social_trend.hashtag= t.post
INNER JOIN oyuncular ON oyuncular.id = t.sid
WHERE
social_trend.tarih > UNIX_TIMESTAMP() ORDER BY social_trend.total DESC LIMIT 5
but looking to your new explanation and img seems you need
SELECT
t.hashtag,
t.total,
t.tarih_trend,
t.sid,
t.tarih,
t.post,
oyuncular.id,
oyuncular.isim
FROM (
select social_post.sid
, social_post.tarih
, social_post.post
, st.hashtag
, st.total
, st.tarih tarih_trend
from social_post
INNER JOIN (
select * from social_trend
WHERE social_trend.tarih > UNIX_TIMESTAMP()
order by total DESC LIMIT 5
) st ON social_post.post LIKE concat('%',st.hashtag,'%' )
ORDER BY social_post.tarih LIMIT 5
) t
INNER JOIN oyuncular ON oyuncular.id = t.sid

SQL Adding count (from 2 tables) to existing select (of 3 tables)

Doing a query on forum database. I am using this query to get thread name, poster, date etc.
(Left only thread_subject for now)
SELECT `thread_subject` FROM `fusion_posts` JOIN `fusion_threads`
ON fusion_posts.thread_id=fusion_threads.thread_id JOIN `fusion_users` ON
fusion_posts.post_author=fusion_users.user_id
GROUP BY fusion_posts.thread_id ORDER BY `post_id` DESC LIMIT 16
Basically, I also need to add something like the count below to the existing select, to count posts of each thread.
SELECT COUNT(*) AS PostCount FROM fusion_posts,fusion_threads WHERE fusion_threads.thread_id = fusion_posts.thread_id group by fusion_threads.thread_id
How could I do that?
Try this:-
SELECT `thread_subject`, COUNT(*) AS PostCount
FROM `fusion_posts` JOIN `fusion_threads`
ON fusion_posts.thread_id=fusion_threads.thread_id JOIN `fusion_users`
ON fusion_posts.post_author=fusion_users.user_id
GROUP BY fusion_posts.thread_id, `thread_subject`
ORDER BY `post_id` DESC
LIMIT 16

MYSQL Union from left and right and group

I have a forum with two tables forum_posts and forum_replies. I need to get the most active users. Here is what I recently tried
SELECT forum_reply.added_by, forum_posts.added_by FROM forum_reply LEFT JOIN forum_posts ON forum_posts.added_by = forum_reply.added_by
UNION
SELECT forum_posts.added_by, forum_reply.added_by FROM forum_posts RIGHT JOIN forum_reply ON forum_reply.added_by = forum_posts.added_by
WHERE forum_reply.date_added < '".$now."' AND forum_reply.date_added > '".$past24h."' AND forum_posts.date_added < '".$now."' AND forum_posts.date_added > '".$past24h."'
GROUP BY forum_reply.added_by, forum_posts.added_by ORDER BY COUNT(*) DESC LIMIT 5");
The problem is this query gives me only one result instead of 5. And the result is definitely not real because the user this query gives me haven't posted anything for the last 24 hours.

multiplying two columns, different tables... one column null

In this join query, i am multiplying two columns from different tables, premium & points. What i want to happen is if there are no columns joined in the premium table then the multiplier will be 1.
here is the query
SELECT parent.*,(premiumtable.bid * pointstable.points) as total FROM strings parent
LEFT JOIN premium premiumtable on parent.sid=premiumtable.sid AND premiumtable.paid='1'
LEFT JOIN points pointstable on parent.sid=pointstable.`string-id`
WHERE parent.category=:category AND (parent.submittype='0' OR parent.submittype='3') GROUP BY parent.id ORDER BY total LIMIT 5
So if nothing is joined on the premiumtable instead of premiumtable.bid * pointstable.points it would be 1 * pointstable.points. The premiumtable.bid acts as a multiplier, if it isn't present, i'd want total to equal pointstable.points
Use a case statement:
SELECT parent.*,
case when premiumtable.bid is null
then pointstable.points
else premiumtable.bid * pointstable.points
end as total
FROM strings parent
LEFT JOIN premium premiumtable on parent.sid=premiumtable.sid AND premiumtable.paid='1'
LEFT JOIN points pointstable on parent.sid=pointstable.`string-id`
WHERE parent.category=:category
AND (parent.submittype='0' OR parent.submittype='3')
GROUP BY parent.id
ORDER BY total
LIMIT 5
Try using COALESCE:
SELECT parent.*,
(COALESCE(premiumtable.bid,1) * pointstable.points) as total
FROM strings parent
LEFT JOIN premium premiumtable
on parent.sid=premiumtable.sid AND premiumtable.paid='1'
LEFT JOIN points pointstable
on parent.sid=pointstable.`string-id`
WHERE parent.category=:category
AND (parent.submittype='0' OR parent.submittype='3')
GROUP BY parent.id
ORDER BY total LIMIT 5

Getting the last 5 records of a joined query

I have a query that does what i want joining table but i need it to change sligtly so i can use it for something else.
I need to get the last 5 records so i should be using the max function and limit it to 5 but it's not working properly
This is my current query, just need to get the last 5 records (probably by the festivalid)
SELECT f.*,
v.total,
v.votes,
v.festivalid,
ifnull(r.reviewcount,0) as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
LEFT OUTER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews
GROUP BY festivalid) as r
ON r.festivalid = v.festivalid
WHERE f.datefrom > CURRENT_TIMESTAMP
ORDER BY f.datefrom, f.eventname
ORDER BY f.datefrom DESC, f.eventname DESC
Limit 5