Reputation: 10748
I have records of photos that users have uploaded in my database. They can specify one of the photos they have uploaded as being a cover photo.
I'd like to query my database to return one photo for each username. If they have cover photo, return that one. If not, pull a normal photo. The column to specify a cover photo is tinyint with a length of 1. The column is either "0"(not a cover photo) or "1"(a cover photo).
I have the following to return all photos for the list of usernames
$usernames = array('bob', 'ted', 'jim');
$usernames = implode( "', '", $usernames );
$query = "SELECT * FROM Photos WHERE username IN('$usernames')";
but i need to combine it with the following, which gets a cover photo if there is one and a normal photo if there isn't for one username.
$query = "SELECT * FROM Photos WHERE username = 'bob' ORDER BY cover DESC LIMIT 1";
I think I need to use the GROUP BY function but I don't know how to set that up. Any suggestions?
Columns are id(bigint), name(varchar(255)), cover(tinyint), username(varchar(30))
Upvotes: 1
Views: 5359
Reputation: 14390
Assuming you have a user table and the photo table has an id column
SELECT p.*
FROM Users u
INNER JOIN Photo p ON p.id = (
SELECT id FROM Photos p2
WHERE p2.username = u.username
ORDER BY cover DESC
LIMIT 1
)
WHERE u.username IN('$usernames');
Upvotes: 3
Reputation: 1270341
In Mysql, you need to do something like:
select p.*
from Photos p left outer join
(select username, min(photoid) as minphotoid
from photos p
where cover = 0
group by username
) pmin
on p.username = pmin.username and
(p.cover = 1 or p.photoid = pmin.minphotoid)
where p.username in ('$usernames')
This is essentially finding one photo (the minimum one) when there is no cover or the cover. There are variations on this with a correlated subquery, which could be faster.
By the way, does p.username in ('$usernames') work in mysql? In other databases, this would only work with one user name in $usernames.
Upvotes: 0
Reputation: 4354
If each record has a Unique identifier (id
), you can do the following:
SELECT P1.* FROM Photos P1
WHERE P1.id IN (SELECT P2.id FROM Photos P2
WHERE P2.username =P1.username
ORDER BY P2.cover DESC LIMIT 1)
AND P1.username IN ('$usernames')
ORDER BY P1.username
Upvotes: 0
Reputation: 6122
If you only want 1 photo per user (cover if it exists, normal if no cover exists)
SELECT max( cover ) , username, photo
FROM Photos
WHERE username IN('$usernames')
GROUP BY username
If you want all normal photos, and only 1 cover photo (if it exists), you can do
SELECT * FROM Photos WHERE cover = 1 AND username IN ('$usernames') GROUP BY username
UNION
SELECT * FROM Photos WHERE cover = 0 AND username IN ('$usernames')
Upvotes: 0