2009-06-28 5 views
5

Je ne suis pas sûr que ce soit la bonne approche, voici ma situation:mysql - sous-requêtes et rejoint

J'essaie actuellement de sélectionner 15 galeries, puis à gauche le rejoindre à la table d'utilisateur à travers le id mais je veux aussi sélectionner une image aléatoire de chaque galerie cependant de ce que je sais que vous ne pouvez pas limiter la jointure gauche (image) pour ne prendre qu'une image aléatoire sans faire de sous-requête.

Voici ce que je suis arrivé à ce jour, mais sa ne fonctionne pas comme il se doit:

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 

J'ai aussi essayé de le faire avec Active Record mais je suis coincé après avoir fait deux à gauche rejoint, est-il possible pour faire obtenir un sous-requête ici:

$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); 

J'espère que ce pas compliqué, mais je commence vraiment à être embrouillé par toutes les requêtes sQL ..

Edit: Active Record with CodeIgniter

+0

+1 pour une citation intéressante de Active Record ... pourriez-vous s'il vous plaît modifier pour inclure un lien? –

Répondre

2

Vous pouvez chercher une image au hasard dans une sous-requête:

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 

Sur la base de votre commentaire, vous pouvez sélectionner une image pour chaque galerie dans une sous-requête. Cela suppose que la table d'images possède une colonne d'ID.

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 
+0

Est-il possible de récupérer deux variables à partir des sous-requêtes? Tout ce que je reçois est "Opérande doit contenir 1 colonne (s)" Par exemple si je veux l'url et le nom sans faire deux sous-requêtes? – Dennis

+0

Une sous-requête comme celle-ci ne peut récupérer qu'une seule colonne (et une seule ligne). Quelle autre colonne souhaitez-vous récupérer? – Andomar

+0

Je voudrais sélectionner à la fois l'url et le nom de l'image, donc je dois faire deux sous-requêtes pour cela? – Dennis

1
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 

Cette requête aller et sélectionnez une galerie, puis il trouvera une galerie avec une image (si vous voulez retourner des galeries sans image, changer INNER JOIN à LEFT OUTER JOIN, et tout ira bien). Après cela, il rejoint les utilisateurs. Maintenant, bien sûr, ce chiot va retourner chaque galerie de frigging pour tous les utilisateurs que vous avez (hoorah!). Vous pouvez limiter l'utilisateur dans la clause WHERE (par exemple, WHERE u.id = 123). Sinon, vous obtiendrez plus de résultats que prévu. Cela, ou faire une INNER JOIN dessus.

+0

Vaut-il mieux faire une jointure interne au lieu de faire comme Andomar l'a expliqué? – Dennis

+0

La jointure vous permet de renvoyer plusieurs colonnes et d'utiliser celles-ci dans votre instruction select. J'ai pensé que c'était peut-être le cas, c'est pourquoi je l'ai fait comme ça. – Eric