2008-10-02 12 views
5

Digamos que tengo dos tablas a las que quiero unirme. Categorías:MySQL Query: LIMITING a JOIN

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

y elementos:

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

Quiero una consulta que devuelve la categoría y la primera (y sólo la primera) itemname:

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

Y hay una forma en que podría obtener resultados aleatorios como:

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

Gracias!

+0

¿Cómo se define "Primero"? Parece el valor de ID más bajo en el artículo? –

+0

Sí, mi mal. Al principio me refiero a la ID más baja. – Eikern

Respuesta

6

acaba de hacer una rápida prueba. Esto parece funcionar:

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) 

Creo que esto cumpliría su primera pregunta. No estoy seguro acerca de la segunda, creo que necesita una consulta interna con orden aleatorio() o algo así.

+0

Tener los resultados al azar no es tan importante para mí, ¡así que esto era realmente lo que estaba buscando! Gracias – Eikern

0

MySQL le permite tener columnas no incluidos en la agrupación o agregado, en cuyo caso lo que tienen valores aleatorios:

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 

O, por mínimos,

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

Recibí un error cuando probé este método: "Cada tabla derivada debe tener su propio alias". Supongo que hice algo mal en alguna parte. – Eikern

0

Mysql no permite incluir columnas no agregadas y no hay garantía de determinismo, pero en mi experiencia casi siempre obtengo los primeros valores.

Así que por lo general (pero no garantizado) esto le dará la primera

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

Si quieres garantiza que tendrá que hacer algo como

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 quieres respuestas aleatorias tendrá para cambiar la subconsulta un poco

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)