I have a site that lets users rate videos based on different tags such as how funny or how interesting they think a video is, allowing users to rate the same video in multiple ways.
The site currently allows sorting videos by specific tags which takes into account the average user rating of the tag for that video. I am now trying to make a MySQL query that can sort videos based on the average aggregate ratings of multiple tags. For example, showing all videos that are both funny and interesting.
I can't figure out how to do this with one query.
This is what to use to sort by one tag
SELECT *, AVG(ratings.rating) as avgTagFunny
FROM videos, ratings
WHERE videos.id = ratings.video_id
AND ratings.tag_id = 2
GROUP BY video_id
ORDER BY avgTagFunny DESC
The closest I got was doing something like this
SELECT *, AVG(ratings.rating) as avgTag, count(distinct tag_id) as distinctTags
FROM videos, ratings
WHERE videos.id = ratings.video_id
AND ratings.tag_id IN (2, 12)
GROUP BY video_id
HAVING distinctTags > 1
ORDER BY avgTag DESC
The problem with this is that it takes the average of all ratings so if 3 users rated how funny a video is and only one rated how interesting it is, the overall average is skewed. What I want is to sort by the average rating of one tag plus the average of another tag divided by 2.
Here's some sample data, as requested.
Tables:
videos: id, title
tags: id, name
users: id, name
ratings: id, user_id, video_id, tag_id, rating
Example data for all ratings of video id 342:
1, 7, 342, 2, 90
2, 10, 342, 2, 80
3, 10, 342, 12, 70
4, 11, 342, 2, 85
5, 7, 342, 12, 50
As you can see, average ratings of tag 2 would be 85 and average ratings of tag 12 would be 60. Average of those two together is 72.5. We don't want the average of all ratings because that would be 75 and skewed towards one tag because there are more of tag 2 than of tag 12.
The first query I posted orders by average ratings of one tag. The second query I posted orders them by all ratings of both tags, but isn't ideal because it's skewed.
I'm looking for a way to order the results by (average ratings of tag 2 + average ratings of tag 12) / 2. I hope that makes sense!
SELECT video_id, AVG(rating) rating
FROM (
SELECT video_id, AVG(rating) rating
FROM ratings
WHERE tag_id IN (2, 12)
GROUP BY
video_id, tag_id
) q
GROUP BY
video_id
ORDER BY
rating DESC
Related
I really am struggling with a MySQL query, I have a table named 'info' and in it I have a column called 'rating' in it I have ratings between 1-10.
Now I need to generate a percentage value of how many ratings are from 1-6 and 7-8 and 9-10 but I need them to display desperately and after that I need a second query that can subtract the percentage value of the results from 1-6 and 9-10.
The query below is as close as I could get from all my research however I don't know how to get a percentage of ratings 1-6 only and not all of them and also how to get a second query to subtract the 1-6 and 9-10 rating percentages. Any help would be amazing.
SELECT rating,
COUNT(*) AS Count,
(COUNT(*) / _total ) * 100 AS Percentege
FROM info,
(SELECT COUNT(*) AS _total FROM info) AS myTotal
GROUP BY rating
Try this:
select if(rating between 1 and 6, '1-6',
if( rating between 7 and 8, '7-8',
'9-10' )
) as rating_range,
count(1) as num
from info
group by rating_range
fiddle code
I have a Ratings(User_ID, Rating) table, The minimum rating for user is 1 and the maximum rating is 12
My question is: How to get users, who have both ratings, 1 and 12 ?
If I correctly understand, you need this:
select user_id from t where
rating IN(1,12)
group by user_id
having count(distinct rating) = 2
If there no chance that same rating may repeated for same user, then you can use count(rating) instead.
I am trying to get the minimum price per travel and know which travel-details correspond to that minimum price per travel.
For this I have tried all kind of variations with subqueries, joins etc. but since there is not 1 primary key I cannot figure it out.
What I'm trying to achieve is get the travel with the lowest price, and then included in the record the details of the travel with that lowest price.
SELECT travel_id, persons, days, MIN(`price`) AS `price`
FROM travel_details
WHERE 1
GROUP BY `travel_id`
HAVING MIN(price);
Simple version of my table-columns, columns are:
travel_id, persons, days, price
Those columns together form the primary key.
A travel can be booked for various persons, days and prices. It can also occur that there are multiple price-options for the same combination of travel_id, persons, and days.
E.g.,
100, 2, 4, **250**
100, 2, 4, **450**
100, 2, **5**, 450
101, 2, 4, 190
101, 2, 5, 185
Being travel_id 100 for 2 persons for 4 persons.
What I would like to achieve is return:
100, 250, and then with correct corresponding values:
100, 2, 4, 250
101, 2, 5, 185
Now my result just mixes all the other data. When I include those columns in the group by, it will not only group on travel_id anymore, but also e.g., on persons. Then it will return all combinations for a travel_id and persons.
Any idea how to approach this?
Select a.travel_id, a.persons, a.days, a.price from travel_details a
JOIN (Select travel_id,MIN(Price) as p from travel_details group by travel_id) b
on b.travel_id=a.travel_id and b.p=a.price
The above query uses self join. Derived table b will contain travel_id along with min price.
SELECT travel_id, persons, days, price
FROM (
SELECT
ROW_NUMBER() OVER(PARTITION BY travel_id, persons, days ORDER BY price) AS RowNum,
travel_id, persons, days, price
FROM travel_details
) X
WHERE X.RowNum = 1
Hello #PeterH, would this work for you?
You can use IN() to do this:
SELECT * FROM travel_details t
WHERE (t.travel_id,t.price) IN(SELECT s.travel_id,min(s.price)
FROM travel_details s
GROUP BY s.travel_id)
GROUP BY t.travel_id; // this last group-by is to filter doubles when there are multiple records per travel with the lowest price.
This question already has an answer here:
Mysql min and max values and corresponding "date" for each month
(1 answer)
Closed 8 years ago.
So I want to be able to show the most expensive movie to rent and the least expensive movie to rent. Basically I want to show the movie title along with its price. Now I am able to get the highest and lowest rental price with this query:
SELECT MAX(rental_rate) as MaxRate, MIN(rental_rate) as MinRate
FROM film;
However how do I edit that query above to show the movie titles in relation to their rates?
I have also tried:
SELECT title (SELECT MAX(rental_rate) FROM film as MaxRate),
(SELECT MIN(rental_rate) FROM film as MinRate)
FROM film;
But that did not work.
Any suggestions?
A proper solution can be found in the question I referred to in comments, but it is a bit complex. I think another, simpler solution would be to ORDER BY rate and use LIMIT to get 1 record. You can use UNION to combine two similar queries to get the lowest and highest rate:
(SELECT title, rental_rate
FROM film
ORDER BY rental_rate
LIMIT 1)
UNION
(SELECT title, rental_rate
FROM film
ORDER BY rental_rate DESC
LIMIT 1)
UNION ALL could be used too, but then you could get the same title if the table contains only one film.
Note that this query will return one lowest rate title and one highest rate title. If you want all titles that share the lowest or highest rate, you'll need that other solution.
What you want is two rows with different conditions, so keep them separate:
(SELECT title, rental_rate, "most expensive" as which_title
from film
ORDER BY rental_rate DESC LIMIT 1)
UNION ALL
(SELECT title, rental_rate, "least expensive" from film
ORDER BY rental_rate ASC LIMIT 1)
with working sqlfiddle: http://sqlfiddle.com/#!2/1e290/3
you can also use below query if you want the min and max of rates with the title of them:
select title, (SELECT MAX(rental_rate) FROM film) from film
where rental_rate=(SELECT MAX(rental_rate) FROM film)
union
select title, (SELECT MIN(rental_rate) FROM film) from film
where rental_rate=(SELECT MIN(rental_rate) FROM film)
hi have a product database which the price is changing every month (period) - I want to show the price-change in percent, grouped by category. The schema is something like this: id, name, category, price, period. (The period is YYYY-MM)
A rows could be:
123, "Chair" , "Furniture", 123 , 2013-05 -- for may
123, "Chair" , "Furniture", 110 , 2013-06 -- for june
Is it possible in a SQL-query to calculate the percentage difference for each product for each month? And at the same time group categories together?
The challenge in this sort of query is finding the previous period. Here is one approach:
select p.*,
(p.price -
(select p2.price
from product p2
where p2.id = p.id and p2.period < p.period
order by period desc
limit 1
) - 1
) * 100 as PercentageChange
from product p
order by category;
It uses a correlated subquery and it makes the assumption that there is a price by every month. By "group categories together", I assume you mean to sort by the category. (Aggregating by the category would lose the information about each product.)
Note that the above syntax could vary by database. Different databases have different way of limiting the results to one row.