Pregunta

Tengo dos tablas players y scores.

Quiero generar un informe que es como la siguiente:

player    first score             points
foo       2010-05-20              19
bar       2010-04-15              29
baz       2010-02-04              13

En este momento, mi consulta es como la siguiente:

select p.name        player,
       min(s.date)   first_score,
       s.points      points    
from  players p    
join  scores  s on  s.player_id = p.id    
group by p.name, s.points

necesito el s.points que se asocia con la fila que vuelve min(s.date). Es que ocurre con esta consulta? Es decir, ¿cómo puedo estar seguro de que estoy recibiendo el valor correcto para el s.points fila unida?

Nota al margen: Me imagino que esto es de alguna manera relacionada con la falta de clasificación densa de MySQL. Cuál es la mejor solución aquí?

¿Fue útil?

Solución

Este es el problema más grande-n-por-grupo que aparece con frecuencia en desbordamiento de pila.

Aquí está mi respuesta habitual:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and s2.date < s.date

where
  s2.player_id is null

;

En otras palabras, dada la puntuación s, tratar de encontrar un s2 punto para el mismo jugador, pero con una fecha anterior. Si no se encuentra ninguna puntuación anterior, entonces S es la más antigua.


Re tu comentario sobre lazos: Tienes que tener una política para la que se debe usar en caso de empate. Una posibilidad es si utiliza incremento automático claves primarias, el que tiene el menor valor es el anterior. Ver el término adicional en la combinación externa a continuación:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and (s2.date < s.date or s2.date = s.date and s2.id < s.id)

where
  s2.player_id is null

;

Básicamente es necesario agregar términos de desempate hasta que llegue a una columna que se garantiza que sea único, al menos para el jugador determinado. La clave principal de la tabla es a menudo la mejor solución, pero he visto casos en los que otra columna era adecuado.

En cuanto a los comentarios que he compartido con @OMG los potros, recuerda que este tipo de prestaciones de consulta enormemente a partir del índice derecho.

Otros consejos

La mayoría RDMBS ni siquiera permitirá incluir columnas no agregadas en su cláusula SELECT cuando se utiliza GROUP BY. En MySQL, que va a terminar con los valores de las filas aleatorias para sus columnas no agregadas. Esto es útil si usted realmente tiene el mismo valor en una columna en particular para todas las filas. Por lo tanto, es bueno que MySQL no restringirnos, aunque es una cosa importante de entender.

Un capítulo entero está dedicado a esto en SQL antipatterns .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top