Question:
write a SQL query that retrieves repeated rentals in which the same
customer rents the same movie more than once. if a customer rents the > same movie multiple times, the output should show this (customer's name, movie's title) combination only once
There are 3 tables:
customer table: (id, name, country, created_date)
movie table: (id, title, duration, release_year)
rental table: (id, customer_id, movie_id)
i currently have:
select customer.name, movie.title
from ((rental inner join customer on rental.customer_id = customer.id) inner join movie on rental.movie_id = movie.id)
group by customer.name, movie.title
having count(*) > 1;
but it is incorrect - any thoughts?
Rewrite your query as:
SELECT c.name, m.title
FROM rental AS r
INNER JOIN customer AS c ON r.customer_id = c.id
INNER JOIN movie AS m ON r.movie_id = m.id
GROUP BY c.name, m.title
HAVING count(*) > 1
;
Your JOIN statements has wrong syntax
EDIT: to avoid naming duplicates change GROUP BY statements:
GROUP BY c.id, m.id
Related
There are 3 types of adventures for which I used distinct function in query.
There is only one 1 customer who have booked all types of adventures.
The query i used to fetch the data is:
select c.customerid,c.name
from customer c
inner join booking b
on c.customerid = b.customerid
inner join destination d
on b.destinationid=d.destinationid
inner join adventure a
on d.adventureid=a.adventureid
group by c.customerid
having count(distinct b.bid)=(select count(*) from bid)
or count(distinct a.adventuretype)=(
select count(distinct a.adventuretype)
from adventure
)
You can get the customer ids using aggregation and having:
select b.customerid
from booking b join
destination d
on b.destinationid = d.destinationid join
adventure a
on d.adventureid = a.adventureid
group by b.customerid
having count(distinct a.advtype) = 3;
Or, if you don't want to hardcode the "3", you can use:
having count(distinct a.advtype) = (select count(distinct advtype from adventure)
I'll leave it up to you to add in the customer name (using join, exists, or in).
I'm new to SQL and I'm hardstuck on this query so I would really appreciate some help/advice:
Tables look like
person: id_person name birth
movie: id_movie movie.title
participation: id_person id_movie
And I'm trying to get the id and name of the film and the name of the actor with most participations of that film (in case that 2 got the same ordered by age/alphabetically) for each film in movie.
So far I got:
SELECT
DISTINCT movie.id, movie.title, t.name, t.num_movies
from
movie
JOIN participation on participation.id_movie = movie.id
JOIN person on participation.id_actor = person.id
JOIN (
SELECT
person.id as id, person.name as name
, person.birth, count(movie.id) as num_movies
from person
JOIN participation on participation.id_actor = person.id
JOIN movie on movie.id=participation.id_movie
GROUP BY person.id
ORDER BY person.birth ASC, person.name ASC
) as t on t.id=person.id
ORDER BY t.num_movies DESC
That gives me all the actors with their participations but I just want the ones with most of each film.
Thanks in advance!
A solution would be to use window functions (for MySQL, this requires version 8.0).
You can first join the tables and do a window count of the total appearances of each actor:
select
m.id movie_id,
m.title movie_title,
p.id person_id,
p.name person_name,
count(*) over(partition by p.id) num_movies
from
movie m
inner join participation pm on pm.id_movie = m.id
inner join person p on p.id = pm.id_person
Then, you can rank the actors of each movie by overall appearances and filter on the top ranked actor of each movie:
select *
from (
select
t.*,
rank() over(partition by movie_id order by num_movies, person_name desc) rn
from (
select
m.id movie_id,
m.title movie_title,
p.id person_id,
p.name person_name,
count(*) over(partition by p.id) num_movies
from
movie m
inner join participation pm on pm.id_movie = m.id
inner join person p on p.id = pm.id_person
) t
) t
where rn = 1
I'm supposed to write a query for this statement:
List the names of customers, and album titles, for cases where the customer has bought the entire album (i.e. all tracks in the album)
I know that I should use division.
Here is my answer but I get some weird syntax errors that I can't resolve.
SELECT
R1.FirstName
,R1.LastName
,R1.Title
FROM (Customer C, Invoice I, InvoiceLine IL, Track T, Album Al) AS R1
WHERE
C.CustomerId=I.CustomerId
AND I.InvoiceId=IL.InvoiceId
AND T.TrackId=IL.TrackId
AND Al.AlbumId=T.AlbumId
AND NOT EXISTS (
SELECT
R2.Title
FROM (Album Al, Track T) AS R2
WHERE
T.AlbumId=Al.AlbumId
AND R2.Title NOT IN (
SELECT R3.Title
FROM (Album Al, Track T) AS R3
WHERE
COUNT(R1.TrackId)=COUNT(R3.TrackId)
)
);
ERROR: misuse of aggregate function COUNT()
You can find the schema for the database here
You cannot alias a table list such as (Album Al, Track T) which is an out-dated syntax for (Album Al CROSS JOIN Track T). You can either alias a table, e.g. Album Al or a subquery, e.g. (SELECT * FROM Album CROSS JOIN Track) AS R2.
So first of all you should get your joins straight. I don't assume that you are being taught those old comma-separated joins, but got them from some old book or Website? Use proper explicit joins instead.
Then you cannot use WHERE COUNT(R1.TrackId) = COUNT(R3.TrackId). COUNT is an aggregate function and aggregation is done after WHERE.
As to the query: It's a good idea to compare track counts. So let's do that step by step.
Query to get the track count per album:
select albumid, count(*)
from track
group by albumid;
Query to get the track count per customer and album:
select i.customerid, t.albumid, count(distinct t.trackid)
from track t
join invoiceline il on il.trackid = t.trackid
join invoice i on i.invoiceid = il.invoiceid
group by i.customerid, t.albumid;
Complete query:
select c.firstname, c.lastname, a.title
from
(
select i.customerid, t.albumid, count(distinct t.trackid) as cnt
from track t
join invoiceline il on il.trackid = t.trackid
join invoice i on i.invoiceid = il.invoiceid
group by i.customerid, t.albumid
) bought
join
(
select albumid, count(*) as cnt
from track
group by albumid
) complete on complete.albumid = bought.albumid and complete.cnt = bought.cnt
join customer c on c.customerid = bought.customerid
join album a on a.albumid = bought.albumid;
Seems you are using count in the wrong place
use having for aggregate function
SELECT R3.Title
FROM (Album Al, Track T) AS R3
HAVING COUNT(R1.TrackId)=COUNT(R3.TrackId))
but be sure of alias because in some database the alias in not available in subquery ..
You should simplify your query. Take a look at this:
SELECT FirstName
, LastName
, Title
FROM (
SELECT C.FirstName
, C.LastName
, A.AlbumID
, A.Title
, COUNT(DISTINCT TrackID) as TracksInvoiced
FROM Customer C
INNER JOIN Invoice I
ON I.CustomerId = C.CustomerId
INNER JOIN InvoiceLine IL
ON I.InvoiceId = IL.InvoiceId
INNER JOIN Track T
ON T.TrackID = I
INNER JOIN Album A
ON A.AlbumID = T.AlbumID
GROUP BY C.FirstName, C.LastName, A.AlbumID, A.Title
) C
INNER JOIN (
SELECT AlbumID
, COUNT(TrackID) as TotalTracks
FROM Track
GROUP BY AlbumID
) A
ON C.AlbumID = A.AlbumID
AND TracksInvoiced = TotalTracks
I used two subselects, the first one counts invoiced tracks per customer and album and joins it with another subselect for each album and amount of tracks on it, only where the two counts are equal.
This one seems to be a little less complicated:
SELECT r.FirstName, r.LastName, r.Title FROM
(
SELECT C.FirstName as FirstName,
C.LastName as LastName,
A.Title as Title,
A.AlbumId as AlbumId,
COUNT(*) as count
FROM Customer C, Invoice I, InvoiceLine IL, Track T, Album A
WHERE C.CustomerId=I.CustomerId
AND I.InvoiceId = IL.InvoiceId
AND T.TrackId = IL.TrackId
AND A.AlbumId = T.AlbumId
GROUP BY C.CustomerId, A.AlbumId
) AS r
WHERE r.count IS IN
(
SELECT COUNT(*) FROM Track T
WHERE T.AlbumId = r.AlbumId
)
Tested the idea on a simpler basis and extended to your example so I don't give a guarantee that you can copy and paste and its working immediately...
I have 3 tables: Book, Customer and Trans. I am trying to write a select query that reports the Name and Book Title of anyone who purchased a book in September. The tables have been successfully created, and all the data is in them, but I can't get this select query to work. I have tried everything. Here is what I have:
SELECT DISTINCT c.Name, b.Title, t.TDate
FROM Customer as c, Book as b, Trans as t;
WHERE c.ID=t.ID AND b.BookID=t.BookID and t.TDate < '2003-10-01';
I'm trying to avoid duplicates as well.
SELECT c.Name, b.Title
FROM Customer as c
JOIN Trans as t ON c.ID = t.ID
JOIN Book as b ON b.BookID = t.BookID
WHERE t.TDate >= '2003-10-01' and t.TDate < '2003-11-01'
GROUP BY c.Name, b.Title
I currently have the following:
Table Town:
id
name
region
Table Supplier:
id
name
town_id
The below query returns the number of suppliers for each town:
SELECT t.id, t.name, count(s.id) as NumSupplier
FROM Town t
INNER JOIN Suppliers s ON s.town_id = t.id
GROUP BY t.id, t.name
I now wish to introduce another table in to the query, Supplier_vehicles. A supplier can have many vehicles:
Table Supplier_vehicles:
id
supplier_id
vehicle_id
Now, the NumSupplier field needs to return the number of suppliers for each town that have any of the given vehicle_id (IN condition):
The following query will simply bring back the suppliers that have any of the given vehicle_id:
SELECT * FROM Supplier s, Supplier_vehicles v WHERE s.id = v.supplier_id AND v.vehicle_id IN (1, 4, 6)
I need to integrate this in to the first query so that it returns the number of suppliers that have any of the given vehicle_id.
SELECT t.id, t.name, count(s.id) as NumSupplier
FROM Town t
INNER JOIN Suppliers s ON s.town_id = t.id
WHERE s.id IN (SELECT sv.supplier_id
FROM supplier_vehicles sv
WHERE sv.vehicle_id IN (1,4,6))
GROUP BY t.id, t.name
Or you could do an INNER JOIN (as your supplier join is INNER, but this will remove towns with no suppliers with those vehicles) and change the COUNT(s.id) TO COUNT(DISTINCT s.id)
If I remember correctly, you can put your second query inside the LEFT OUTER JOIN condition.
So for example, you can do something like
...
LEFT OUTER JOIN (SELECT * FROM Suppler s, Supplier_vehicles ......) s ON s.town_id=t.id
In that way you are "integrating" or combining the two queries into one. Let me know if this works.
SELECT t.name, count(s.id) as NumSupplier
FROM Town t
LEFT OUTER JOIN Suppliers s ON t.id = s.town_id
LEFT OUTER JOIN Supplier_vehicles v ON s.id = v.supplier_id
WHERE v.vehicle_id IN (1,4,6)
GROUP BY t.name