I'm using mysql. I have two tables, one is about movie type, and the other is about movie rating with timestamps. I want to join these two tables together with movie id to count the average rating for each type of movie. I'm trying to extract only the movie types which have at least 10 ratings per film and the ratings made in December, and order by the highest to lowest average rating.
Table 'types'
movieId
type
1
Drama
2
Adventure
3
Comedy
...
...
Table 'ratings'
movieId
rating
timestamp
1
1
851786086
2
1.5
1114306148
1
2
1228946388
3
2
850723898
1
2.5
1167422234
2
2.5
1291654669
1
3
851345204
2
3
944978286
3
3
965088579
3
3
1012598088
1
3.5
1291598726
1
4
1291779829
1
4
850021197
2
4
945362514
1
4.5
1072836909
1
5
881166397
1
5
944892273
2
5
1012598088
...
...
...
Expect result: (Nb ratings >= 10 and rate given in December)
type
Avg_Rating
Drama
3.45
I'm trying to write the query like below, but I'm not able to execute it. (around 10 thousand data in original table)
Where should I adjust my query?
SELECT DISTINCT T.type, AVG(R.rating) FROM types AS T
INNER JOIN ratings AS R ON T.movieId = R.movieId
WHERE R.timestamp LIKE (
SELECT FROM_UNIXTIME(R.timestamp,'%M') AS Month FROM ratings
GROUP BY Month
HAVING Month = 'December')
GROUP BY T.type
HAVING COUNT(R.rating) >=10
ORDER BY AVG(R.rating) DESC;
I see two problems:
timestamp LIKE - what's that supposed to do?
and
inner query with GROUP BY by without any aggregation. Perhaps you meant WHERE? And anyway you don't need it at all - just do the same check for December directly on timestamp, w/o LIKE and w/o subquery
SELECT DISTINCT T.type, AVG(R.rating) FROM
types AS T INNER JOIN ratings AS R
ON T.movieId = R.movieId
WHERE FROM_UNIXTIME(R.timestamp,'%M') = 'December'
GROUP BY T.type
HAVING COUNT(R.rating) >=10
ORDER BY AVG(R.rating) DESC;
You can try next query.
SELECT DISTINCT T.type, AVG(R.rating) FROM types AS T
INNER JOIN ratings AS R ON T.movieId = R.movieId
GROUP BY T.type
HAVING
COUNT(R.rating) >= 10 -- have 10 or more rating records
AND SUM(MONTH(FROM_UNIXTIME(R.timestamp)) = 12) > 0 -- have at least one rating in December
ORDER BY AVG(R.rating) DESC;
sqlize
Related
I have 3 tables
1.users
user_id nationality
1 Egyptian
2 Palestinian
3 French
centers
id center_name
1 q
12 y
5 x
23 z
centers_users
student_id center_id
1 12
2 5
3 5
1 23
2 12
what I expect
Nationality center_name count_of_users_from this country
Egyptian y,z 10
Palestinian x,y 33
French x,q 7
I have tried many mysql queries but I cannot get the result I want
Final query I execute:
SELECT * from (SELECT (LENGTH(GROUP_CONCAT(DISTINCT user_id))-ENGTH(REPLACE(GROUP_CONCAT(DISTINCT user_id), ',', ''))) as ss,GROUP_CONCAT( DISTINCT user_id) ,nationality from user where user_id in(SELECT student_id FROM `centers_users`) GROUP by nationality)a
But only get the count with nationality.
When I Join with centers gives me redundancy because I cannot put "ON" condition with
group_concat
How can I implement it?
Thanks..
I think you want to join the tables and aggregate:
select u.nationality,
group_concat(distinct c.center_name) as center_names,
count(distinct user_id) as users_from_this_country
from users u join
user_centers uc
on u.user_id = uc.student_id join
centers c
on c.center_id = uc.center_id
group by u.nationality;
You may be able to use count(*) for users_from_this_country. It depends on how you want to count a user who is in multiple centers in the same country.
I have a problem to count distinct elements in a group by this element.
Let me explain this, I have two tables:
tb1
team amount
1 90
2 80
3 70
4 50
5 60
tb2
team player
5 1
1 1
3 2
1 2
2 2
1 3
3 3
4 3
5 3
2 4
The expected result is:
player nb_team Sum_amount nb_player
1 2 150 3
2 3 240 4
3 4 270 3
4 1 80 2
I'm doing this:
SELECT tb2.player, COUNT(DISTINCT tb1.team) as nb_team,
SUM(tb1.amount) AS sum,
(SELECT COUNT(DISTINCT tb2.player)
FROM tb2 where tb1.team=tb2.team) AS nb_player
FROM tb1, tb2
WHERE tb1.team=tb2.team
GROUP BY tb2.player
ORDER BY tb2.player ASC;
The 3 first columns are correct but I can't get the right value for nb_player.
I have to count how many players are included by the number of teams
For example for the first line result:
player 1 is playing in 2 teams that involved 3 players in total (player #1,#2 and #3)
any idea?
Counting teams and summing those teams amounts for a player needs a different resultset than counting players playing with given player in the same team. So I suggest using two different subqueries and then joining them on the player.
SELECT teams_total.player, teams_total.nb_team, teams_total.`sum`,
players_total.nb_players
FROM
( SELECT tb2.player, COUNT(DISTINCT tb1.team) as nb_team,
SUM(tb1.amount) AS `sum`
FROM tb1 JOIN tb2 ON tb1.team=tb2.team
GROUP BY tb2.player ) teams_total
JOIN
( SELECT tb2_1.player, COUNT(DISTINCT tb2_2.player) as nb_players
FROM tb2 tb2_1
JOIN tb1 ON tb2_1.team=tb1.team
JOIN tb2 tb2_2 ON tb2_2.team=tb1.team
GROUP BY tb2_1.player ) players_total
ON teams_total.player=players_total.player
ORDER BY teams_total.player ASC;
You can use the following query:
SELECT player,
COUNT(DISTINCT t2.team) AS nb_team,
SUM(amount) AS Sum_amount,
(SELECT COUNT(DISTINCT(player))
FROM tb2 AS t
WHERE INSTR(CONCAT(',',GROUP_CONCAT(DISTINCT t2.team), ','),
CONCAT(',',t.team,',')) <> 0) AS nb_player
FROM tb2 AS t2
INNER JOIN tb1 AS t1 ON t2.team = t1.team
GROUP BY player
GROUP_CONCAT is used in the correlated sub-query in order to get a comma separated list of all teams related to the player of the outer query. Using INSTR on this list, we can filter tb2 rows and count the DISTINCT number of players of these teams.
Demo here
I'm trying to sum multiple tables using Joins and Sums in MySQL and not having much success.
My Tables (Unnecessary Columns Removed)
Students
idStudent studentname studentyear
1 foobar 11
2 barfoo 11
3 thing 8
Athletics_Results
idResult idStudent points
1 1 14
2 1 11
3 3 7
4 2 9
Team_Results
idTeamResults year points
1 11 9
2 8 8
3 7 14
So let me explain about the tables, because I admit they're poorly named and designed.
Students holds the basic info about each student, including their year and name. Each student has a unique ID.
Athletics_Results stores the results from athletics events. The idStudent column is a foreign key and relates to idStudent in the student column. So student foobar (idStudent 1) has scored 14 and 11 points in the example.
Team_Results stores results from events that more than one student took part in. It just stores the year group and points.
The Aim
I want to be able to produce a sum of points for each year - combined from both athletics_results and team_results. EG:
year points
7 14 <-- No results in a_r, just 14 points in t_r
8 15 <-- 7 points in a_r (idResult 4) and 8 in t_r
11 43 <-- 14, 11, 9 points in a_r and 9 in t_r
What I've tried
For testing purposes, I've not tried combining the a_r scores and t_r scores yet but left them as two columns so I can see what's going on.
The first query I tried:
SELECT students.studentyear as syear, SUM(athletics_results.points) as score, SUM(team_results.points) as team_score
FROM students
JOIN team_results ON students.studentyear = team_results.year
JOIN athletics_results ON students.idStudent = athletics_results.idStudent
GROUP BY syear;
This gave different rows for each year (as desired) but had incorrect SUMS. I learnt this was due to not grouping the joins.
I then created this code:
SELECT studentyear as sYear, teamPoints, AthleticsPoints
FROM students st
JOIN (SELECT year, SUM(tm.points) as teamPoints
FROM team_results tm
GROUP BY year) tr ON st.studentyear = tr.year
JOIN (SELECT idStudent, SUM(atr.points) as AthleticsPoints
FROM athletics_results atr
) ar ON st.idStudent = ar.idStudent
Which gave correct SUMS but only returned one year group row (e.g the scores for Year 11).
EDIT - SQLFiddle here: http://sqlfiddle.com/#!9/dbc16/. This is with my actual test data which is a bigger sample than the data I posted here.
http://sqlfiddle.com/#!9/ad111/7
SELECT tr.`year`, COALESCE(tr.points,0)+COALESCE(SUM(ar.points),0)
FROM Team_Results tr
LEFT JOIN Students s
ON tr.`year`=s.studentyear
LEFT JOIN Athletics_Results ar
ON s.idStudent = ar.idStudent
GROUP BY tr.year
According to your comment and fiddle provided
check http://sqlfiddle.com/#!9/dbc16/3
SELECT tr.`year`, COALESCE(tr.points,0)+COALESCE(SUM(ar.points),0)
FROM (
SELECT `year`, SUM(points) as points
FROM Team_Results
GROUP BY `year`) tr
LEFT JOIN Students s
ON tr.`year`=s.studentyear
LEFT JOIN Athletics_Results ar
ON s.idStudent = ar.idStudent
GROUP BY tr.year
Try this http://sqlfiddle.com/#!9/2bfb1/1/0
SELECT
year, SUM(points)
FROM
((SELECT
a.year, SUM(b.points) AS points
FROM
student a
JOIN at_result b ON b.student_id = a.id
GROUP BY a.year) UNION (SELECT
a.year, SUM(a.points) AS points
FROM
t_result a
GROUP BY a.year)) c
GROUP BY year;
On your data I get:
year points
7 14
8 15
11 43
Can be done in multiple ways. My first thought is:
SELECT idStudent, year, SUM(points) AS totalPoints FROM (
SELECT a.idStudent, c.year, a.points+b.points AS points
FROM students a
INNER JOIN Athletics_Results b ON a.idStudent=b.idStudent
INNER JOIN Team_Results c ON a.studentyear=c.year) d
GROUP BY idStudent,year
I'm trying to figure out how to grab the average rating for each salesperson over their last 100 ratings if they are currently employed, and if they have an average rating less than 3 (out of 5).
I have the following tables (leaving out information that isn't needed in the query):
users
id name employed
-----------------------
1 John 1
2 Sue 1
3 Bob 0
...
sales
id users_id
------------------
100 3
101 2
102 3
103 1
...
ratings
sales_id rating
-----------------
100 4
101 5
102 5
103 2
...
The current query I have searches everything and returns the average for all orders ever but I want it to only grab the most recent 100 ratings (or less if the salesperson hasn't sold that many items), still excluding anyone that is no longer employed or has a rating for their last 100 orders greater than 3. This is the current query:
SELECT u.name, avg(r.rating) as avg_rating, count(r.rating)
FROM users AS u
JOIN sales AS s ON s.users_id = u.id
JOIN ratings AS r ON r.sales_id = s.id
WHERE u.employed = 1
GROUP BY u.id
HAVING avg_rating <= 3;
Any help would be great! Thanks! :D
You can use my sql variables to keep track of the number of ratings so that you can get only recent 100 ratings , ordering by sales_id so you get recent ratings.
SQL FIDDLE DEMO
SELECT T.name, avg(T.rating) as avg_rating, count(T.rating)
FROM
(
SELECT u.name, r.rating, #num := if (#name = name, #num+1, 1) as rn,
#name:= name as var_name
FROM users AS u
JOIN sales AS s ON s.users_id = u.id
JOIN ratings AS r ON r.sales_id = s.id
AND u.employed = 1
JOIN ( select #name :='' , #num :=1) var
order by sales_id desc
)T
where T.rn <=100
GROUP BY T.name
HAVING avg_rating <= 3
I am having a scenario where students of a college do a research on a subject. Each subject has some value (marks) for it. A student can do research on multiple subjects.
I have the following table hierarchy:
student (s)
---------------
student_id subject_id
1 2
2 1
2 3
3 1
3 3
4 2
4 3
.....
research_subjects (r)
-----------------------------
id value
1 5
2 10
3 20
4 40
....
Now i am fetching the student records along with their total research value with this query:
select student_id, sum(r.value) as total from student s inner join research_subjects r on s.subject_id=r.id group by student_id
This gives results like the following:
student_id total
1 10
2 25
3 25
4 30
As you see, the results are grouped by student_id. But what i want is to group the results by total value. So i want to get rid of duplicate rows for the total, in the output. (i.e., have only 1 record with the total=25).
I tried using: group by total in the query (instead of group by student_id), but it gives an error.
Is there any other way of grouping the results by the column that contains 'sum' value?
Try this:
select count(student_id), total
from (
select student_id, sum(r.value) as total
from student s
inner
join research r on s.subject_id=r.id group by student_id
) s2
group by total
Try this:
select Count(student_id) as students, total
from
(
select student_id, sum(r.value) as total
from student s inner join research r on s.subject_id=r.id
group by student_id
) s
group by total
Or this:
select Min(student_id) as student_id, total
from
(
select student_id, sum(r.value) as total
from student s inner join research r on s.subject_id=r.id
group by student_id
) s
group by total