MySQL relational view - join? - mysql

I'm relatively new to MySQL and I'm having no end of difficulty trying to work out how to do this. I've researched joining and such but I'm not really sure how to apply this.
I have three tables:
Artists Table
ID,
Name,
Description
Albums Table
ID,
Title,
Year,
Artist_ID
Tracks Table
ID,
Title,
Album_ID
Tracks are assigned to albums and albums are assigned to artists. (I did this through the relation view in phpmyadmin, engine is InnoDB).
What I'm trying to do is query ALL of the tracks for a particular artist (from their ID).
Is anyone able to point me in the right direction? Thanks in advance!

Using the implicit join syntax:
SELECT * FROM Tracks, Artists, Albums
WHERE Tracks.Album_ID=Albums.ID AND Albums.Artist_ID=Artists.ID
AND Artists.Name='foo'
Explicitly:
SELECT * FROM Artists
LEFT JOIN Albums ON Artists.ID=Albums.Artist_ID
LEFT JOIN Tracks ON Tracks.Album_ID=Albums.ID
WHERE Name='foo'
Or, with nested subqueries:
SELECT * FROM Tracks WHERE Album_ID IN
(SELECT ID FROM Albums WHERE Artist_ID IN
(SELECT ID FROM Artists WHERE Name='foo'))`
All three of these are identical (in the absence of NULL values). I recommend using the second one, as it is what seems to be selected by most SQL experts.

Use:
SELECT t.title
FROM TRACKS t
JOIN ALBUMS al ON al.id = t.album_id
JOIN ARTISTS a ON a.id = al.artistid
WHERE a.name = ?
If you already have the artists.id value:
SELECT t.title
FROM TRACKS t
JOIN ALBUMS al ON al.id = t.album_id
WHERE al.artist_id = ?

You may want to try the following:
SELECT tracks.title
FROM tracks
INNER JOIN albums ON (albums.id = tracks.album_id)
INNER JOIN artists ON (artists.id = albums.artist_id)
WHERE artists.name = 'A particular arist name';
Note that JOIN is a synonym for an INNER JOIN. We're basically using simple join syntax, using the inner join operation, which is probably the most common join type. I hope this gets you going in the right direction.

SELECT track.*
FROM artists, albums, tracks
WHERE artist.ID = 123
AND artist.id = albums.artist_ID
AND albums.id = tracks.Album_ID

Related

MySQL: How to count references to references to a table?

Say I have a database of publishers, who employ authors, who write books.
Or to phrase it another way, each book, is written by an author, who works for a publisher.
publishers: id
authors: id, publisher_id
books: id, author_id
I know how to get a list of publishers with how many authors each employs, from this question.
How do I get a list of publishers with how many books each has published?
How can I get both - publishers, each with number of authors and number of books?
try this
SELECT COUNT(DISTINCT b.`id`) noofbooks,COUNT(DISTINCT au.id) noofauthers,pub.id publisher FROM publisher pub
INNER JOIN auther au ON au.`pub_id`= pub.`id`
INNER JOIN books b ON b.`aut_id` = au.`id` GROUP BY pub.id
You need a three table join
SELECT publisher.id, count(*) from publisher
INNER JOIN author on publisher.id = author.publisher_id
INNER JOIN book on author.id = book.author_id GROUP BY publisher.id;
You just need to fire a simple sql join query for that like as follow.
SELECT p.publishers , COUNT(a.authors) totalAuthors, COUNT(b.books) TotalBooks
FROM publishers AS p,authors AS a ,books AS b
WHERE p.publishersid = a.publishersid
AND a.authorsid = b.authorsid
GROUP BY p.publishersid;
I ended up with something similar to bhanu's answer:
SELECT publishers.*,
COUNT(DISTINCT authors.id) AS 'author_count',
COUNT(DISTINCT books.id) AS 'book_count'
FROM publishers
LEFT JOIN authors ON (authors.publisher_id = publishers.id)
LEFT JOIN books ON (books.author_id = authors.id)
GROUP BY publishers.id;

MySQL Selecting from one table while needing data from other

I have such tables:
How to, with just SQL select all the comments, for tracks with the genre of 'xxx'?
Well you could do that in two way first:
SELECT commmentId, content, date
FROM comments
WHERE trackId IN (SELECT trackId
FROM tracks
WHERE genreId = xxx);
Or:
SELECT c.commentId, c.content, c.date, t.genreId
FROM comments c
INNER JOIN tracks t
ON c.trackId = t.trackId
WHERE t.genreId = xxx;
And I didn't understand very well if you want to select comments by genreId or by genre name (if you want to do that by name than you should extend this a little bit) but this is the logic you should fallow...

How to select photos that are in selected albums

I couldn't figure out how to word this question, so I'm going to use a typical example. Imagine I have a common design for photo albums with 3 tables - photos, albums, photo_albums (a lookup table). Albums names are A, B and C.
How would I find all photos that are in both A and C?
If your table design look like this and you want to filter on the album name. Then you can do this:
SELECT
*
FROM
photos
WHERE EXISTS
(
SELECT
NULL
FROM
photo_albums
JOIN albums
ON photo_albums.albumId=albums.albumId
WHERE
photos.photoId=photo_albums.photoId
AND albums.albumName IN ('A','B')
)
I think the better solution would be to do it via the Id if you have one. Like this:
SELECT
*
FROM
photos
WHERE EXISTS
(
SELECT
NULL
FROM
photo_albums
WHERE
photos.photoId=photo_albums.photoId
AND photo_albums.albumId IN (1,3)
)
You first do a JOIN between albums and photo_albums and do a GROUP BY to find which photos are there in both albums A and C. Then JOIN this result with photos to get the final result.
Something like this:
SELECT p.*
FROM photos p
JOIN (
SELECT pa.photoid
FROM albums a
JOIN photos_albums pa
ON a.albumid = pa.albumid
WHERE a.albumname IN ('A','C')
GROUP BY pa.photoid
HAVING COUNT(DISTINCT(pa.albumid)) = 2
) t
ON p.photoid = t.photoid
Working Fiddle: http://sqlfiddle.com/#!2/187f36/20

how to only show one rows with the same value through joined tables

I have the id of an artist and I'd like to know all the albums released by this artist.
MySQL Structure
Example Mysql Query
SELECT album_name
FROM albums AS a,
tracks AS t,
produced AS p
WHERE p.produced_track = t.track_id
AND t.track_album = a.album_id
AND p.produced_artist = "17"
Problem
As an album has many tracks, my result will show a couple of time the same album. In order to make a discography, I'd like to have all the albums from an artist.
Is there a way to do that in MySQL ?
Just use SELECT DISTINCT as:
SELECT DISTINCT album_name
FROM albums AS a,
tracks AS t,
produced AS p
WHERE p.produced_track = t.track_id
AND t.track_album = a.album_id
AND p.produced_artist = "17"
This should do it...
Instead of retrieving too many rows and removing duplicates you can also use a sub-query
SELECT album_name
FROM albums AS a
WHERE album_id IN (SELECT t.track_album
FROM tracks t
JOIN produced AS p ON p.produced_track = t.track_id
WHERE p.produced_artist = 17)
You should also get used to using explicit JOIN syntax instead of the implicit joins hidden in the WHERE clause
You should try: SELECT DISTINCT album_name
FROM albums AS a,
tracks AS t,
produced AS p
WHERE p.produced_track = t.track_id
AND t.track_album = a.album_id
AND p.produced_artist = "17"

Inner join statement with limit in one of three tables

I'm trying to get data from three tables (photos, albums, album_photos),
then the program searches a user's albums in the album table, then look for every album the ID's of the photos in album_photos, and then, for each ID, look at the photos table all data by ID.
Yesterday I asked something like this: Inner join with 3 tables, but now, I think the question is different, I'm wondering how I can add a limit to a request by inner join.
So, I'm working now in this code:
SELECT a.album_name, a.album_id, c.*
FROM albums a
INNER JOIN album_photos b ON a.album_id = b.album_id
INNER JOIN photos c ON b.photo_id = c.photo_id
WHERE (
SELECT COUNT(*)
FROM album_photos d
WHERE b.album_id = d.album_id
AND d.nick = :nick
) <=5
Ok, this code select's the albums that have 5 or less photos. I do not want the code to do that, no matter how many photos have the album, I want to show the album with a LIMIT OF 5 photos.
Other people have told me that you can not do it, I believe that this is not so, because the SQL language is very complex and I think we should have the tool to do it.
Is there any way to do this in a proper way?
*In the link that I'm shared above I put an example about the output data.
Try changing the where clause to this:
WHERE (
SELECT COUNT(*)
FROM album_photos d
WHERE d.album_id = b.album_id and
d.photo_id <= b.photo_id
AND d.nick = :nick
) <= 5
This counts the number of photos in order, not just the number of photos in the album.
Since album_photos has a mapping relationship between photos and albumns, you can specify the number of photos to join on by using TOP:
SELECT a.album_name, a.album_id, p.*
FROM albums a
INNER JOIN album_photos ap ON
ap.photo_id = (select top 5 photo_id from album_photos where a.album_id = ap.album_id order by photo_id)
INNER JOIN photos p ON ap.photo_id = p.photo_id
The Order by photo_id in the subquery will ensure the same 5 (or fewer) photos are returned
EDIT PER COMMENT. Modifying to use MySql LIMIT instead of T-SQL TOP
SELECT a.album_name, a.album_id, p.*
FROM albums a
INNER JOIN album_photos ap ON
ap.photo_id = (select photo_id from album_photos where a.album_id = ap.album_id order by photo_id LIMIT 0, 5)
INNER JOIN photos p ON ap.photo_id = p.photo_id