views:

1060

answers:

2

Hey,

I'm not quite sure if this is the right approach, this is my situation:

I'm currently trying to select 15 galleries and then left join it with the user table through the id but I also want to select one random picture from each gallery however from what I know you can't limit the left join (picture) to only pick up one random picture without doing a subquery.

Here is what I got so far but its not working as it should:

SELECT galleries.id, galleries.name, users.username, pictures.url 
FROM galleries 
LEFT JOIN users ON users.id = galleries.user_id 
LEFT JOIN pictures ON (
    SELECT pictures.url 
    FROM pictures 
    WHERE pictures.gallery_id = galleries.id 
    ORDER BY RAND() 
    LIMIT 1) 
WHERE active = 1 
ORDER BY RAND() 
LIMIT 15

I also tried to do this with Active Record but I got stuck after doing two left joins, is it possible to do get a subquery in here:

$this->db->select('galleries.id, galleries.name, users.id as user_id, users.username');
$this->db->from('galleries');
$this->db->join('users', 'users.id = galleries.user_id','left');
$this->db->join('pictures','pictures.gallery_id = galleries.id AND','left');
$this->db->where('active',1);

I hope its not to messy but I'm really starting to get confusing by all the sql queries..

Edit: Active Record with CodeIgniter

+1  A: 
SELECT
    g.id,
    g.name,
    u.username,
    p.url
FROM
    galleries g
    INNER JOIN (SELECT DISTINCT
         gallery_id,
         (SELECT url FROM pictures ss WHERE ss.gallery_id = s.gallery_id 
             ORDER BY RAND() LIMIT 1) AS url
     FROM
         pictures s) p ON
        g.id = p.gallery_id
    LEFT OUTER JOIN users u ON
        g.user_id = u.id
WHERE
    g.active = 1

This query will go out and select a gallery, then it will find any gallery with a picture (if you want to return galleries without a picture, change INNER JOIN to LEFT OUTER JOIN, and you'll be fine). After that, it joins it up with users. Now, of course, this puppy is going to return every frigging gallery for however many users you have (hoorah!). You may want to limit the user in the WHERE clause (e.g.-WHERE u.id = 123). Otherwise, you're going to get more results than you'd expect. That, or do an INNER JOIN on it.

Eric
Is it better to do an inner join instead of doing as Andomar explained?
Dennis
The join allows you to return multiple columns and use those in your select statement. I figured this may be the case, which is why I did it like that.
Eric
+1  A: 

You could fetch a random picture in a subquery:

select 
    g.name, u.username,
    (select url from pictures p where p.gallery_id = g.gallery_id 
     order by rand() limit 1) as url
from galleries g
left join users u on g.user_id = u.id
where g.active = 1

Based on your comment, you could select a picture for each gallery in a subquery. This is assuming the picture table has an ID column.

select 
    g.name, u.username, p.url, p.name
from (
    select id, user_id, name,
        (select id from pictures p 
         where p.gallery_id = g.gallery_id 
         order by rand() limit 1) as samplepictureid
    from galleries
    where g.active = 1
) g
left join users u on g.user_id = u.id
left join pictures p on p.id = g.samplepictureid
Andomar
Is it possible to retrieve two variables from the sub-queries?All I get is "Operand should contain 1 column(s)"For example if I want the url and the name without doing two sub-queries?
Dennis
A subquery like this can only retrieve one column (and one row.) Which other column would you like to retrieve?
Andomar
I would like to select both the url and the name from the picture, so I have to do two sub-queries for this?
Dennis
Two subqueries would run the risk of selecting different pictures. Answer edited with an alternative approach.
Andomar