2008-10-02 2 views
5

Dites que j'ai deux tables que je veux rejoindre. Catégories:Requête MySQL: LIMITER un JOIN

id name 
---------- 
1 Cars 
2 Games 
3 Pencils 

et articles:

id categoryid itemname 
--------------------------- 
1 1   Ford 
2 1   BMW 
3 1   VW 
4 2   Tetris 
5 2   Pong 
6 3   Foobar Pencil Factory 

Je veux une requête qui retourne la catégorie et le premier (et seul le premier) itemname:

category.id category.name item.id item.itemname 
------------------------------------------------- 
1   Cars   1  Ford 
2   Games   4  Tetris 
3   Pencils  6  Foobar Pencil Factory 

Et est-il façon dont je pourrais obtenir des résultats aléatoires comme:

category.id category.name item.id item.itemname 
------------------------------------------------- 
1   Cars   3  VW 
2   Games   5  Pong 
3   Pencils  6  Foobar Pencil Factory 

Merci!

+0

Comment définir "Premier"? Il ressemble à la plus faible valeur d'ID dans l'élément? –

+0

Ouais, ma mauvaise. En premier je veux dire l'ID le plus bas. – Eikern

Répondre

6

juste fait un rapide tester. Cela semble fonctionner:

mysql> select * from categories c, items i 
    -> where i.categoryid = c.id 
    -> group by c.id; 
+------+---------+------+------------+----------------+ 
| id | name | id | categoryid | name   | 
+------+---------+------+------------+----------------+ 
| 1 | Cars | 1 |   1 | Ford   | 
| 2 | Games | 4 |   2 | Tetris   | 
| 3 | Pencils | 6 |   3 | Pencil Factory | 
+------+---------+------+------------+----------------+ 
3 rows in set (0.00 sec) 

Je pense que cela répondrait à votre première question. Pas sûr de la seconde - je pense que cela nécessite une requête interne avec ordre par random() ou quelque chose comme ça!

+0

Avoir des résultats aléatoires n'est pas si important pour moi, alors c'était vraiment ce que je cherchais! Merci – Eikern

0

Mysql vous permet d'avoir des colonnes non incluses dans le regroupement ou l'agrégat, dans ce cas, ils ont des valeurs aléatoires:

select category.id, category.name, itemid, itemname 
    inner join 
     (select item.categoryid, item.id as itemid, item.name as itemname 
     from item group by categoryid) 
    on category.id = categoryid 

Ou, pour les peines minimales,

select category.id, category.name, itemid, itemname 
inner join 
    (select item.categoryid, min(item.id) as itemid, item.name as itemname 
    from items 
    group by item.categoryid) 
on category.id = categoryid 
+0

J'ai une erreur quand j'ai essayé cette méthode: "Chaque table dérivée doit avoir son propre alias". Je suppose que j'ai fait quelque chose de mal quelque part. – Eikern

0

Mysql laisse inclure des colonnes non agrégées et il n'y a aucune garantie de déterminisme, mais dans mon expérience, j'ai presque toujours les premières valeurs.

Donc, en général (mais pas garanti) cela vous donnera la première

select * 
from categories c, items i 
where i.categoryid = c.id 
group by c.id; 

Si vous voulez la garantie que vous aurez besoin de faire quelque chose comme

select categories.id, categories.name, items.id, items.name 
from categories inner join 
    items on items.categoryid = categories.id and 
    items.id = (select min(items2.id) from items as items2 where items2.categoryid = category.id) 

Si vous voulez des réponses aléatoires que vous aurez pour modifier un peu la sous-requête

select categories.id, categories.name, items.id, items.name 
    from categories inner join 
     items on items.categoryid = categories.id and 
     items.id = (select items2.id from items as items2 where items2.categoryid = category.id order by rand() limit 1)