2012-03-04 14 views
9

Tengo dos tablas (país & patos) donde la tabla de países tiene todos los países del mundo y la tabla patos tiene una lista de patos con un campo country_id para vincular al país principal.MySQL return primera fila de una tabla unida

Estoy tratando de obtener una lista de los únicos países con al menos un pato y con eso un único registro coincidente de la tabla de patos para el pato mejor calificado dentro de ese país. Hasta ahora tengo:

SELECT * 
FROM country c 
INNER JOIN ducks d ON c.id = d.country_id 
ORDER BY c.country ASC, d.rating DESC 

Esto devuelve una lista de cada pato en lugar de solo uno por país.

Estaría agradecido si alguien puede indicarme la dirección correcta aquí. Prefiero hacerlo en SQL que tener una consulta por separado para cada país para sacar el pato mejor calificado.

+2

Ver: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax- row-per-group-in-sql/para ejemplos de cómo hacer esto. – imm

+0

¿Qué pato quieres? ¿alguien? – dotoree

+1

@dotoree La clasificación más alta (patos más altos) desde el conjunto –

Respuesta

19
SELECT c.*, d.* 
FROM country c 
    INNER JOIN ducks d 
    ON d.id =       --- guessing the ducks Primary Key here 
     (SELECT dd.id     --- and here 
     FROM ducks dd 
     WHERE c.id = dd.country_id 
     ORDER BY dd.rating DESC 
     LIMIT 1 
     ) 

un índice en (country_id, rating, id) para la tabla MyISAM o (country_id, rating) para la tabla InnoDB, w debería ayudar.

Esta consulta mostrará un solo duck por país, incluso si más de uno tiene la misma calificación. Si desea que aparezcan patos con calificación empatada, use la respuesta de @ imm GROUP BY.

+0

Gracias que funciona perfectamente –

+0

@ imm's anwer está bien, también. –

+0

+1 Muy agradable. ¿Es posible lograr esto sin ninguna subconsulta? –

-1

Muchas bases de datos tienen algún equivalente de "seleccionar los 10 mejores desde ...". En mySql, la sintaxis sería "select * from ... limit 10".

... PERO ...

En este caso, uou realmente quieren "grupo por" y "max()"!

+1

Hola, el grupo limita los resultados, pero la función MAX() solo muestra el máximo para el grupo, pero el resto de la fila contiene los datos para el grupo. primer registro encontrado por MySQL en lugar del que tiene la calificación máxima. Esto es lo que tengo hasta ahora: 'SELECT c. *, D. *, MAX (d.rating) FROM country c INNER JOIN patos d ON c.id = d.country_id GROUP BY c.country SOLICITAR POR c.country ASC, d.rating DESC' –

0

Prueba esto:

SELECT c.country, MAX(d.rating) AS max_rating 
FROM country c 
JOIN ducks d ON c.id = d.country_id 
GROUP BY c.id 
ORDER BY c.country ASC 

Si la "calificación más alta" es 1, a continuación, cambiar MAX(d.rating) a MIN(d.rating)

+0

Hola, eso está muy cerca, ya que devuelve un único país con la calificación máxima, estoy tratando de devolver también el registro que corresponde a esa calificación máxima. por ejemplo, si cambio la primera línea de tu código a 'SELECCIONAR c.country, d.id, d.rating, MAX (d.rating)', entonces d.rating no siempre es igual a MAX (d.rating) si eso hace que sentido –

+0

Sí, lo hace. He actualizado la respuesta. Inténtalo de nuevo. –

+0

@ J.Bruni: 'HAVING' después de' ORDER BY' no es una sintaxis válida. –

3

Usted puede tratar de:

SELECT c.*, d.* 
FROM country c 
INNER JOIN (
    SELECT d.country_id, d.id, MAX(d.rating) AS rating 
    FROM ducks d 
    GROUP BY d.country_id 
) q ON (q.country_id = c.id) 

INNER JOIN ducks d 
    ON (d.country_id, d.rating) = (q.country_id, q.rating) 
+0

Esto solo necesita una unión más para mostrar los detalles de los patos: 'INNER JOIN ducks d ON (d.country_id, d.rating) = (q.country_id, q.rating)' –

+0

@ ypercube, cierto dat. – imm

8

Usted podría intentar simplemente añadiendo una selección de unirse, por

SELECT c.*, d.* 
FROM country c 
INNER JOIN ducks d ON c.id = d.country_id 
LEFT JOIN ducks d2 ON d.country_id = d2.country_id AND d2.rating > d.rating 
WHERE d2.id IS NULL 
+0

¡Genial! Me gusta esta versión –

+1

Y es mejor tener 'SELECT c. *, D. *'. No es necesario incluir las columnas 'd2. *', Que serán todas NULL. –

+1

Esta debería ser la respuesta aceptada – ScottG

Cuestiones relacionadas