SQL count by group - sql

I have to following schema
Movie(mvID, title, rating, year)
Director(directorID, firstname, lastname)
Genre(mvID*, genre)
Direct(mvID*, directorID*)
I need to know the director that directed to most movies of say the comedy genre and output their details with the count of how many movies they made in the that genre.
So I have
SELECT Director.DirectorID, Director.FirstName, Director.LastName, COUNT(*)
FROM Direct, Genre, Director
WHERE Direct.mvID = Genre.mvID
AND Genre.genre = 'Comedy'
AND Direct.DirectorID = Director.DirectorID
AND COUNT(*) > ALL
GROUP BY Director.DirectorID, Director.FirstName, Director.LastName
ORDER by COUNT(*) DESC
but I get a group function not allowed error.

The SQL below will solve your problem:
SELECT Director.DirectorID, Director.FirstName, Director.LastName, COUNT(*)
FROM Direct, Genre, Director
WHERE Direct.mvID = Genre.mvID
AND Genre.genre = 'Comedy'
AND Direct.DirectorID = Director.DirectorID
AND rownum = 1
GROUP BY Director.DirectorID, Director.FirstName, Director.LastName
order by COUNT(*) DESC
Specifically, this joins the tables and counts the movies directed by each director for movies of genre 'Comedy'. Then it sorts the row in descending order of count and grabs the first row.
Note you have two many<->many relationships so if you weren't only looking at comedy (i.e. if you ran this across multiple genres), you would probably have to use a different technique (i.e. multiple temp tables or similar virtual aggregates) in order to not have 'double counting in your SQL...
Also note that if two directors have the same count of movies for this genre, only one row would be brought back. You would have to modify the sql slightly if you wanted all directors with the same count of comedies to be returned.
Cheers,
Noah Wollowick

select d.firstname,d.lastname,count(g.mvId)
from Director d
inner join Direct dr on d.directorId=dr.directorId
inner join Genre g on dr.mvId=g.mvId
where g.genre='comedy'
group by d.firstname
having count(g.mvId)=max(g.mvId)

Related

counting individual elements that meet a certain criteria without duplicates in sqlite3

I'm trying to count all the individual actors from movies in 2004 the problem is when I tried using the count() function it returned how much times every actor appeared in a movie that year.
basically I cant get count() to play well with the GROUP BY function.
SELECT COUNT(name) FROM people
INNER JOIN stars ON stars.person_id = people.id
INNER JOIN movies ON stars.movie_id = movies.id
WHERE movies.year = 2004
GROUP BY name;
relevant tables: movies (id, title, year), stars (movie_id, person_id), people (id, name)
You just need to count the number of DISTINCT person_id in stars (no need to use the people table at all) that have been in movies made in 2004:
SELECT COUNT(DISTINCT person_id) AS num_actors
FROM stars
JOIN movies ON movies.id = stars.movie_id
WHERE movies.year = 2004
Apparently you are not specifying the field you intent to be used for aggregation.Query will return name of actors and respective count of movies. Try below,
SELECT name,COUNT(*) FROM people
INNER JOIN stars ON stars.person_id = people.id
INNER JOIN movies ON stars.movie_id = movies.id
WHERE movies.year = 2004
GROUP BY name;

SQL ORDER BY number of rows?

How do you ORDER BY number of rows found in another table? I have a table for animals (these are livestock animals) and another table for awards. When an animal wins an award, the award gets added to the awards table.
People want to be able to find the animals who have won the most awards (WHERE award type is 1), ordered from most awards to least. How do I ORDER BY how many awards they have if the awards are in a separate table each with their own row?
SELECT animals.id
FROM animals
LEFT JOIN awards ON animals.id = awards.animalid
WHERE awards.type = 1
ORDER BY...
You would seem to want GROUP BY:
SELECT a.id
FROM animals a LEFT JOIN
awards aw
ON a.id = aw.animalid AND aw.type = 1
GROUP BY a.id
ORDER BY COUNT(aw.animalid) DESC;

How to count number of items in a specific type in a table in sql?

I have a table named Movie, with actors attribute. actors_type is specific and looks like this:
GEORGE.ACTOR_TYPE('Clint Eastwood', 'Christopher Carley', 'Bee Vang', 'Ahney Her')
ACTOR_TYPE is implemented as a varray(5) of varchar(20)
the query I tried to count the number of movies for each actor is :
select m.title, a.column_value, count(m.title)
from movie m, table(m.actors) a
group by m.title, a.column_value
order by a.COLUMN_VALUE
which gives me a count of each row(?) Not the count of movies for each actor. the output is as below:
what I am trying to get is to List actors that acted in multiple movies and show movie title and the actor.
but when I add m.title in the select statement, it will count each row.
This is the other query I wrote:
select a.column_value, count(m.title)
from movie m, table(m.actors) a
having count(m.title) > 1
group by a.column_value
order by a.COLUMN_VALUE
and the result is:
I need to add the title to the output too, but when I add it, all the counts will be one, as the first table.
Movie Table:
There is no table for Actors, we create table for it via table(m.actors) a to access its items
You have to remove m.title from group by and selection cause you are going to count that according to actor.I assume column_value is a common column between two tables , so i used that on join
You need to try like below
select a.column_value, count(m.title)
from movie m
join m.actors a on m.column_value=a.column_value
group by a.column_value
order by a.COLUMN_VALUE

sql get a unique ID then count the number of tuples relating to that ID

Database Structure
MovieInfo (mvID, title, rating, year, length, studio)
DirectorInfo(directorID, firstname, lastname)
MemberInfo(username, email, password)
ActorInfo(actorID, firstname, lastname, gender, birthplace)
CastInfo(mvID*, actorID*)
DirectInfo(mvID*, directorID*)
GenreInfo(mvID*, genre)
RankingInfo(username*, mvID*, score, voteDate)
Query
I need to get the director with the largest number of comedy movies. (I'm also required to use the ALL operator). My understanding is getting the list of mvid where genre = 'Comedy" and directorid:
select mvid
from genreinfo
where genre = 'Comedy'
union all
select directorid
from directorinfo
;
But then how do I count the number of movies a specific director has? And how do I get that single one with the highest count of "comedy" movies?
You're on the right track. I'd recommend looking at JOINs.
I've provided a step-by-step answer on how to obtain the desired results. If you just want the final query, go down to step 5 and pick the one appropriate for your DBMS.
1: Selecting all comedy movie IDs:
SELECT mvid
FROM GenreInfo
WHERE genre = 'Comedy';
2: Selecting the directorIDs of those movies
SELECT directorID
FROM DirectInfo
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy';
3: Selecting the director name of those directors.
SELECT firstname
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy';
4: Grouping that query by director to get number of movies:
SELECT firstname, COUNT(*) AS NumberOfMovies
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy'
GROUP BY DirectorInfo.directorID;
5: Sort the results and get only the first one:
SELECT firstname, COUNT(*) AS NumberOfMovies
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy'
GROUP BY DirectorInfo.directorID
ORDER BY NumberOfMovies
LIMIT 1;
If you're using SQL server, use TOP instead:
SELECT TOP 1 firstname, COUNT(*) AS NumberOfMovies
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy'
GROUP BY DirectorInfo.directorID
ORDER BY NumberOfMovies;
You can use a join and group by to get the result.
select DirectorID,COUNT(mvid)
from DirectInfo d
inner join genreinfo g
ON d.mvid=g.mvid
where genre ='Comedy'
GROUP BY DirectorID
ORDER BY COUNT(mvid)
This is homework? Well, right now you are selecting a list of IDs, some of them representing directors, others representing movies. You notice that this is not at all what you are supposed to do, right?
What you want is a list of directors. So you select from the DirectorInfo table. You also want information about his movies (excatly: the number of movies of a certain kind). So you must join that information from MovieInfo. Now think about what else you need to glue together to get from director to their movies. Then think about how to glue in that genre criterium.
Once you have joined it all together, then you group your results. You want one record per director (instead of ane record per director and movie), so you make a group and count within that group.
I hope this helps you solve your task. Good luck!
select di.directorid, count(1) as 'no_of_comedy_movies'
from DirectorInfo di inner join join DirectInfo dri
on di.directorid = dri.directorid
inner join genreinfo gi
on gi.mvid = dri.mvid
where gi.genre = 'Comedy'
group by dri.directorID
order by no_of_comedy_movies

SQL select on a many-to-many table

I've got 3 tables: Movies, Actors, and MovieActors. MovieActors is a many-to-many relationship of Movies and Actors with columns MovieActorId, MovieId, and ActorId
How do I find movies that have a certain set of actors in it? For example I want to find all movies that have both Michael Fassbender (actor Id 1) and Brad Pitt (actor Id 2) in them. What would the query look like?
One way is to join the tables. Filter for the actors and then insure the count has the number of actors you want in it (2 in this case)
SELECT
m.MovieID
FROM
Movies m
INNER JOIN MovieActors ma
ON m.MovieID = ma.MovieID
WHERE
ma.ActorID IN (1,2)
GROUP BY
m.MovieID
HAVING COUNT(DISTINCT ma.ActorID) = 2
DEMO
Note
Thanks to user814064 for pointing out that since Actors can have more than one role on a movie we need to count the DISTINCT ma.ActorID not just * The SQL Fiddle Demo demonstrates the difference
select m.movieid
from movies m
inner join movieactors ma on ma.movieid = m.movieid
where ma.actorid in (1,2)
group by m.movieid
having count(distinct ma.actorid) = 2
To keep it simple, you can just do two in clauses:
select * from Movies m
where m.MovieId in (select MovieId from MovieActors where ActorId = 1)
and m.MovieId in (select MovieId from MovieActors where ActorId = 2)
Performance may not be as good as a single join, but it's clean and easy to read.