SQL : query to retrieve data - sql

I'm working on a SQL project where i have the tables Actor AlbumId TrackId InvoiceLine and Invoice and i want to retrieve the names of the actors whose tracks are the top 3 sold.
ex(from a table of 10 artists ) .
Drake (300 tracks sold )
Kendrick (233 tracks)
Cardi B (200 tracks)
I'm new to SQL and i have my diagram below . I know that i have to connect the tables of actor album track and invoice to get the 3 max(count(trackid)) from the invoiceline table to give me the names of the actors that have made the specific tracks
Thank you for your time

Below joins the relevant tables together and uses the aggregrate COUNT function to count the number of invoice lines associated with a song.
You may want to use TOP 3 WITH TIES in case there are two artists in third place with same number of sales
SELECT TOP 3
ar.Name
FROM InvoiceLine il
JOIN Track t
ON il.TrackId = t.TrackId
JOIN Album al
ON al.AlbumId = t.AlbumId
JOIN Artist ar
ON ar.ArtistId = al.ArtistId
GROUP BY ar.Name
ORDER BY COUNT(t.TrackId) DESC

If you're looking for the top 3 tracks sold then this will give you the top 3 trackids. Then join this to your Track, Album and Artist tables to get the artist.
SELECT TOP 3 trackid
FROM InvoiceLine
GROUP BY trackid
ORDER BY COUNT(trackid) DESC

Related

SQL multiple Joing Question, cant join 5 tables, problem with max

I got 6 tables:
Albums
id_album | title | id_band | year |
Bands
id_band | name |style | origin
composers
id_musician | id_song
members
id_musician | id_band | instrument
musicians
id_musician | name | birth | death | gender
songs
id_song | title | duration | id_album
I need to write a query where I get the six bands with more members and of those bands, get the longest song duration and it's title.
So far, I can get the biggest bands:
SELECT bands.name, COUNT(id_musician) AS numberMusician
FROM bands
INNER JOIN members USING (id_band)
GROUP BY bands.name
ORDER BY numberMusician DESC
LIMIT 6;
I can also get the longest songs:
SELECT MAX(duration), songs.title, id_album, id_band
FROM SONGs
INNER JOIN albums USING (id_album)
GROUP BY songs.title, id_album, id_band
ORDER BY MAX(duration) DESC
The problem occurs when I am trying to write a subquery to get the band with the corresponding song and its duration. Trying to do it with inner joins also gets me undesired results. Could someone help me?
I have tried to put the subquery in the where, but I can't find how to do it due to MAX.
Thanks
I find that using lateral joins makre the query easier to write. You already have the join logic all right, so we just need to correlate the bands with the musicians the songs.
So:
select b.name, m.*, s.*
from bands b
cross join lateral (
select count(*) as cnt_musicians
from members m
where m.id_band = b.id_band
) m
cross join lateral (
select s.title, s.duration
from songs s
inner join albums a using (id_album)
where a.id_band = b.id_band
order by s.duration desc limit 1
) s
order by m.cnt_musicians desc
limit 6
For each band, subquery m counts the number of musicians per group (its where clause correlates to the outer query), while s retrieves the longest song, using correlation, order by and limit. The outer query just combines the information, and then orders selects the top 6 bands.

I need a count of each track sold in an album then display all album names and it's corresponding track name that has max count in sql

sales table shows how many of each track is sold. I need to count of each track sold
album table shows album names common field is trackid
I need album name, only track title that's sold max in that album and count of that track sold.
select al.title as album, t.name as track, max(s.sales)
from tracks t, albums al,
(select al.title as album, count(i.trackid) as sales
from albums al, tracks t, invoice_items i
where t.trackid = i.trackid and t.albumid = al.albumid
group by album)s
where t.albumid = al.AlbumId;

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;

Is there a way to count and loop with plain SQL?

I have the following tables:
album:
albumID, albumTitle, albumReleaseDate, albumLabel, albumDigitalImg, albumCoverStory
albumTrack:
trackID, albumID, recordingID, albumTrackNumber, cd
italic = primary key
bold = foreign key
The question is as follows:
List the total number of tracks on each album that has any. Give the
column containing the total number of tracks a sensible name and use
albumId to identify each total.
My only idea would be to iterate over each albumID and check how many tracks are assigned to it but obviously loops aren't a thing in plain SQL? Is there any way to do this using plain SQL?
This only checks how many tracks are assigned for albumID 1, not for all albums and I'm really lost as to how I could do this without a loop.
SELECT COUNT(albumID)
FROM albumTrack
WHERE albumID = 1;
I'm using Oracle.
Below query will give you the number of tracks against each albumID,if any.
SELECT albumID,count(trackID) as NumberOfTracks
FROM albumTrack
Group By albumID;
You can try:
Select ab.albumID,
Count(Distinct trackID) As trackCount
From album ab
Inner Join albumTrack at
on at.albumID = ab.albumID
Group By ab.albumID;
This will give the count of tracks for each album.
The question asks for the counts per albumID.
For just that, a select on albumTrack alone with a GROUP BY on the albumID should be sufficient.
SELECT albumID, COUNT(*) AS TotalTracks
FROM albumTrack
GROUP BY albumID
ORDER BY albumID
But if albumTrack.albumID can be NULL, or isn't a foreign key on album.albumID?
Then an INNER JOIN on the "album" table should still be used.
To make sure that it only counts for albumID's that actually exist in the "album" table.
SELECT
tracks.albumID,
COUNT(*) AS TotalTracks
FROM albumTrack AS tracks
JOIN album ON album.albumID = tracks.albumID
GROUP BY tracks.albumID
ORDER BY tracks.albumID
And if you'd like to show the counts per albumTitle:
SELECT
a.albumTitle,
COUNT(t.trackID) AS TotalTracks
FROM album a
JOIN albumTrack t ON t.albumID = a.albumID
-- WHERE a.albumID = 1
GROUP BY a.albumID, a.albumTitle
ORDER BY a.albumTitle

help with a sql query joining 2 many-many tables

i want help how to solve this sql problem.
suppose i have 3 tables
Movie
ID
Name
Genre
ID
Name
Movie_Genre (this one is the link for many to many)
FK_MovieID
FK_GenreID
i want to select all the movies that are of genre 1 and genre 3
how is this possible?
i can only select the movies of 1 genre but not the movies that are of 2 genres using
SELECT Movie.ID, Movie.Name
FROM Movies
INNER JOIN Movie_Genre ON Movie_Genre.FK_MovieID=Movie.ID
AND Movie_Genre.FK_GenreID = 1
Use:
SELECT m.id,
m.name
FROM MOVIE m
JOIN MOVIE_GENRE mg ON mg.fk_movieid = m.id
AND mg.fk_genreid IN (1, 3)
GROUP BY m.id, m.name
HAVING COUNT(DISTINCT mg.fk_genreid) = 2
The last line is key to getting rows from both genre's - the DISTINCT means duplicate associations (IE: two instances of genre 1) will be ignored because they are false positives. But the count must equal the number of genres you are looking for.
But COUNT(DISINCT isn't supported by all databases. You should mention what you are using - if not by tag, then in the question... If the primary key for the MOVIE_GENRE table is both fk_movieid and fk_genreid, then it's not an issue. Next best thing would be that both the columns are in a unique constraint/index...