tags:

views:

89

answers:

1

Hi. I have a table containing persons information (one row per person) and another table containing persons photos filenames (many rows per person). I want to select a group of persons (based on another table) but only one photo per person.

My old SQL was like this:

SELECT persons.personID, persons.name, persons.photo_filename, movie_cast.role
FROM persons, movie_cast
WHERE persons.personID = movie_cast.personID
AND movie_cast.imdbID = ?
ORDER BY movie_cast.castORDER
LIMIT 9';

But here, the 'persons' table contains also a 'photo_filename' column. In my new database design, this column is in another table. So if I try to get the photo_filename from the new table I get all the photos available for each person, but I need to get only one.

How to do it?

+3  A: 

In the first example I have assumed there is always a photo, and am just grabbing the highest sorted photo filename alphabetically as a means to get a consistent photo for each user each time you run the query.

SELECT p.personID, p.name, ph.photo_filename, mc.role 
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID 
INNER JOIN (
    select personID, max(photo_filename) as MaxPhotoName
    from photos
    group by personID
) phm on p.personID = phm.personID
INNER JOIN photos ph on phm.personID = ph.personID 
    and phm.MaxPhotoName = ph.photo_filename
WHERE mc.imdbID = ? 
ORDER BY mc.cast 
LIMIT 9

If there is a photo_date column and you want to use the newest photo you can do it like this:

SELECT p.personID, p.name, ph.photo_filename, mc.role 
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID 
INNER JOIN (
    select personID, max(photo_date) as MaxPhotoDate
    from photos
    group by personID
) phm on p.personID = phm.personID
INNER JOIN photos ph on phm.personID = ph.personID 
    and phm.MaxPhotoDate = ph.photo_date
WHERE mc.imdbID = ? 
ORDER BY mc.cast 
LIMIT 9

If there is not always a photo, you can use a LEFT OUTER JOIN so that you will still get all your records back:

SELECT p.personID, p.name, ph.photo_filename, mc.role 
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID 
LEFT OUTER JOIN (
    select personID, max(photo_date) as MaxPhotoDate
    from photos
    group by personID
) phm on p.personID = phm.personID
LEFT OUTER JOIN photos ph on phm.personID = ph.personID 
    and phm.MaxPhotoDate = ph.photo_date
WHERE mc.imdbID = ? 
ORDER BY mc.cast 
LIMIT 9
RedFilter
Great! The last code example is exactly what I need (because theres not always a photo) but instead of selecting the photo by date I need to select it by photo_status. photo_status being 1 for main photo and 0 for other.
Jonathan