Connecting multiple tables and using self join - mysql

I have a problem regarding a mysql query. What I'm supposed to do is find the pair of actors that acted in most of films together.
I have 3 tables:
actor - has id and name
casting - has movieid, actorid and ord
movie - has id (own id, not the one from actor), title, year, score, votes and director.
So, I did the following query:
SELECT *
FROM ( SELECT a.actorid,
b.actorid,
c.name,
d.name,
COUNT(*) AS zajednicka_pojavljivanja
FROM casting a,
casting b,
actor c,
actor d,
WHERE a.movieid=b.movieid AND a.actorid<>b.actorid
GROUP BY a.actorid,b.actorid,c.name,d.name) tablica_temp
ORDER BY zajednicka_pojavljivanja DESC;
What I get is an error:
ERROR
1064 (42000): You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near 'WHERE a.movieid=b.movieid AND a.actorid<>b.actorid GROUP BY
a.actorid) tablica_t' at line 1
I don't know where the problem is, can anyone help?

You're pretty close. The <> on your original query simply needed to be set to < or > but not <> and then you needed to limit your results or use a select max(count) approach to get all of the same counts.
SELECT A.ActorID, B.ActorID, Count(*) MostFilms
FROM Casting A
INNER JOIN Casting B
ON A.MovieID = B.MovieID and A.ActorID < B.ActorID
Group by A.ActorID, B.ActorID
order by MostFilms Desc
Limit 1
Basically what this says is join casting to itself getting the paired actors by movie. the < on A.ActorID to B.ActorID eliminates actor to him/herself and the opposites so if Actor A and B exist, B to A will not be included.
ordering by the MostFilms descending will return only that pair with the most.
The downfall to this is if two pairs have the same count only one of them would be returned.
If you need the names of the actors you can add two joins one for each casting table.

You have an extra comma in the FROM clause. Change:
actor d,
to
actor d

Related

Why does this sql query provide error? Is there a better way to get what I am looking for?

I have this problem I have to solve. It has to be applied on the chinook database. I am looking for combinations of song formats and genres that describe 50 or more songs.
They have to be in descending order based on the number of songs they describe.
So far I have come up with this.
SELECT DISTINCT mediatype.Name, genre.Name, COUNT(*)
FROM (SELECT * FROM mediatype JOIN track WHERE track.MediaTypeId = mediatype.MediaTypeId
UNION
SELECT * FROM genre JOIN track WHERE genre.GenreId = track.GenreId)
WHERE (mediatype.MediaTypeId, genre.GenreId) IN (
SELECT track.MediaTypeId, track.GenreId
FROM track GROUP BY track.MediaTypeId, track.GenreId
HAVING COUNT(*) > 50)
This, however provides an error that says
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE (mediatype.MediaTypeId, genre.GenreId) IN...'`
Can anybody explain as to why this error pops up?
Can any body offer a better solution?
Thanks in advance!
You should be joining the mediatype and genre tables with the subquery that finds the combinations with at least 50 songs.
SELECT distinct m.Name AS format, g.name AS genre, mg.song_count
FROM (
SELECT mediaTypeId, genreId, COUNT(*) AS song_count
FROM track
GROUP BY mediaTypeId, genreID
HAVING song_count > 50
) AS mg
JOIN mediatype AS m ON m.mediaTypeId = mg.mediaTypeId
JOIN genre AS g ON g.genreId = mg.genreId
ORDER BY mg.song_count

Why this error is showing 'Error Code: 1146. Table 'sakila.t' doesn't exist'?

I want to find the names of actors who did perform in maximum number of films using DERIVED table. How this error is coming out?
my query
select actor from
(
select distinct(actor.first_name) as 'actor',count(film.film_id) as 'film_count' from actor
join film_actor on film_actor.actor_id=actor.actor_id
join film on film.film_id=film_actor.film_id
group by actor
order by film_count
) as t
where film_count=(select max(film_count) from t);
my query + error message
database sakila
SELECT actor FROM
(
SELECT DISTINCT(actor.first_name) AS 'actor',
COUNT(film.film_id) AS 'film_count'
FROM
actor
JOIN
film_actor
ON film_actor.actor_id=actor.actor_id
JOIN
film ON
film.film_id=film_actor.film_id
GROUP BY actor.first_name
ORDER BY film_count
) AS t order by film_count desc
LIMIT 1
You cannot refer to table 't' created inside subquery directly in a where clause outside the subquery. instead use the above query. i have ordered the result by film_count column in descending order and taken the first row to get actor with largest number for film_count

SQL if number of hires leaves 1 left (Use column alias in where clause)

I am having a small issue with a simple SQL statement.
I need to find out if I have 7 copies of a movie in the movie table and 6 people have rented it out, I need to see that I only have 1 copy left (I need to do this all through the SQL query). I know normally I would do it using PHP and just takeaway the number hired from the total number of copies, but sadly my college wants me to do it the other way.
SELECT *,
COUNT(distinct hire.movie_id) AS num_orders
FROM `movie`
INNER JOIN hire ON hire.movie_id = movie.id
WHERE num_orders < movie.no_copies;
When I run this I get the following issue #1054 - Unknown column 'num_orders' in 'where clause'.
You can't use an alias in a where predicate - you either need to repeat the predicate, wrap the query in a derived table before filtering on the alias, or you can also use HAVING as per below (in MySql, at least).
I don't see the need for DISTINCT h.movie_id (since you want to count the rentals? - possibly DISTINCT h.hireid ?), and it seems you will need to group by the movies to count the number of rentals.
How about:
SELECT m.id, m.no_copies, COUNT(h.movie_id) AS num_rentals
FROM `movie` m
INNER JOIN hire h ON h.movie_id = m.id
GROUP BY m.id, m.no_copies
HAVING num_rentals < m.no_copies;

Database Count & Group By error

I am quite new on SQL and I am trying to practice to improve myself.
I have a database which has a
Table : Players, Teams, Plays, and Wins
Players : pid, pname, age, country
Plays : pid, season, tid, value ( pid -> pid in Players, tid -> tid in Teams )
Teams : tid, tname, tcolor, tbudget
Wins : wtid, ltid, season, wscore, lscore ( wtid,ltid -> tid in Teams )
The question is Find the name of the players whose played in atleast 2 dif. teams with same color
What I did is
SELECT DISTINCT P.pname
FROM Players P
,Teams T1
GROUP BY T1.tcolor
HAVING 1 < (
SELECT COUNT (10)
FROM Teams T2
WHERE T1.tcolor=T2.tcolor)
When I try to query this , I get an error which is ;
Error Code: 1630
FUNCTION PRALATEST.COUNT does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual
In which part am I doing wrong?
Try this:
select pname
from Players
join Plays on Plays.pid = Players.pid
join Teams on Teams.tid = Plays.tid
group by pname, tcolor
having count(Teams.tname) > 1
The condition count(Teams.tname) > 1 is in a having clause instead of a where clause becuase it needs to operate on the results AFTER the group by is performed.
Couple things. Your error message is because you put a numeric constant in the COUNT function. You should just use an asterisk.
Also, you have not specified a join condition for your Players and Teams tables. As a result, you are doing a product join (probably not what you want). I'm guessing you need to join to your Plays table.
You should change your coding practice to use "explicit" join syntax to avoid errors like this in the future.

The following SQL zoo query is apparently wrong

I have a problem with the following exercise query on this page http://sqlzoo.net/3.htm :
4d. List the 1978 films by order of cast list size.
I'm trying to do the query:
SELECT DISTINCT(m1.title), COUNT(c1.actorid)
FROM ((movie AS m1 JOIN casting AS c1 ON m1.id=c1.movieid) JOIN actor AS a1 ON a1.id=c1.actorid)
WHERE m1.yr=1978
GROUP BY m1.title
ORDER BY COUNT(c1.actorid) DESC
But it doesn't give the right answer, and I don't know why. Am I wrong?
This should do it:
select m.title, count(c.actorid)
from movie m
join casting c on c.movieid = m.id
where m.yr = 1978
group by m.title
order by 2 desc
As you don't need any information from the actors, you don't need to include that table in the join.
Btw: your usage of distinct shows two misunderstandings:
distinct is not a function. It always operates on all columns of the result
when you do a group by there is no need to also to a distinct (as the group by will already return only the distinct values of the grouped columns)