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
Related
I have a table called "articles" which has a column called article char and photo_ID int.
And I also have a table called photos.
It has 2 columns photo_ID and photo_name.
I need to select photo name from table photos, but take its ID from table articles.
I tried this, but I'm doing something wrongly.
Can someone help?
The code is:
CREATE TABLE articles(Article CHAR(35) NOT NULL, Photo_ID INT(5) NOT NULL);
CREATE TABLE photos(Photo_ID INT(5) NOT NULL, Photo_name CHAR(35));
INSERT INTO photos VALUES
(1, "one.png"),
(2, "two.png"),
(3, "three.png");
INSERT INTO articles VALUES
("one", 1),
("two", 2),
("three", 3);
SELECT Photo_name
FROM photos
WHERE articles.Photo_ID = photos.Photo_ID = 2;
And the last select doesn't work. I get error Unknown column 'articles.Photo_ID' in 'where clause'
Your select is wrong you need a proper join and a proer where clause
SELECT photos.Photo_name
FROM photos
INNER JOIN articles ON articles.Photo_ID=photos.Photo_ID
WHERE photos.Photo_ID=2;
You have to write Proper select & join with where clause.
SELECT p.Photo_name
FROM photos p
LEFT JOIN articles a ON a.Photo_ID=p.Photo_ID
WHERE p.Photo_ID = 2;
You are not using the table articles the same way you are using a database, so you can't call articles.Photo_ID in your WHERE clause.
try instead
SELECT Photo_name FROM photos WHERE photos.Photo_ID=2;
and this should work.
when you specity FROM photos, don't call articles.Photo_ID because the table articles is not loaded.
So if you want to load the article table, you should try doing a JOIN ... ON ...
like
SELECT article, photo_name FROM photos LEFT JOIN articles ON articles.Photo_ID = photos.Photo_ID WHERE articles.Photo_ID =2;
Maybe this is new stuff for you, there's 4 type of JOIN : LEFT, RIGHT, INNER, OUTER.
Okay I hope this helps.
Ciao
You need to Join tables.
SELECT p.Photo_name FROM photos p
JOIN articles a
ON p.id = a.Photo_ID
WHERE p.id=2;
P.S Better to change column names
articles
id
article
photo_id
photos
id
name
SELECT p.name FROM photos p
JOIN articles a
ON p.id = a.photo_id
WHERE p.id=2;
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...
i have 3 tables audios,videos,images
they all have dateadded and uid
i want to select all (select *) from these tables where uid=1 and order all the results by dateadded, very confused what the query would be like?
if tha tables hold the same information you can use union, e.g.:
select name, date_added
from(
select video_name as name,date_added, uid
from videos
union all
select audio_name as name,date_added, uid
from audios
union all
select image_name as name,date_added, uid
from images
) u
where uid = 1
order by date_added
If the 3 table has 1 same field like groupID or something like that you can use left join or inner join depending on what output would you want to have.
using left join:
select * from videos v left join audios a on v.groupID = a.groupID
left join images i on v.groupID = i.groupID
note:
just change the word "left" to "inner" if you want to use the other type of join.
It doesn't have to have the same field name "groupID". But it is necessary to have a common functionality or it represents something which is related to each other.
Links:
here are some links that may help you
http://www.w3schools.com/sql/sql_join.asp
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
enjoy coding..:)
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
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