sql >> Base de Datos >  >> RDS >> Mysql

Problemas para obtener el recuento correcto con una unión

Creo que el enfoque más directo de lo que está intentando hacer es simplemente usar subconsultas correlacionadas.

Por lo tanto, el primer ejemplo justo debajo devuelve los resultados que está buscando . Puede modificarlo fácilmente para excluir las filas con cero goles y asistencias.

Utiliza el valor team_id en cada subconsulta, pero puede proporcionarlo con una variable o parámetro, como se muestra, de modo que solo necesita especificar el valor una vez:

set @team_id := 2;

select
    p.id as player_id
    , p.last_name
    , (
        select count(*)
        from goals
        where player_id = p.id
        and team_id = @team_id
    ) as goals
    , (
        select count(*)
        from assists
        inner join goals on assists.goal_id = goals.id
        where assists.player_id = p.id
        and goals.team_id = @team_id
    ) as assists
from players p

Para el equipo 1:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     2 |       1 |
|  2 | Lemieux   |     0 |       0 |
|  3 | Messier   |     1 |       1 |
+----+-----------+-------+---------+

Para el equipo 2:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     0 |       0 |
|  2 | Lemieux   |     1 |       0 |
|  3 | Messier   |     0 |       0 |
+----+-----------+-------+---------+

Para el equipo 3:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     0 |       1 |
|  2 | Lemieux   |     0 |       0 |
|  3 | Messier   |     1 |       0 |
+----+-----------+-------+---------+

Epílogo

Desde la perspectiva de tratar de hacer esto con menos subconsultas y/o con consultas agregadas, tiene un par de problemas con su primer intento.

Un problema es que su consulta probablemente no funcionará correctamente si no incluye todos los campos en su group by cláusula a pesar de que MySQL no se quejará de eso como (¿la mayoría?) Otras bases de datos lo harán.

Además, debido a que los registros tanto en las tablas de asistencias como en las de jugadores solo se relacionan indirectamente con los equipos a través de la tabla de goles, es bastante difícil obtener un resumen independiente de los goles y las asistencias con una sola consulta.

Como una especie de ilustración, otras respuestas tempranas a esto, incluida mi primera oportunidad rápida, tenían un par de problemas:

  • Si un jugador tuvo asistencias para un equipo, pero no tuvo ningún gol para ese equipo, las consultas no podrían arrojar ningún resultado para esa combinación de jugador y equipo. Los resultados estaban incompletos.

  • Si un jugador tuvo goles para un equipo, pero no tuvo asistencias para ese equipo, las consultas aún devolverían un número positivo de asistencias cuando deberían haber arrojado cero. Los resultados fueron realmente incorrectos, no solo incompletos .

Justo debajo hay una solución un poco más correcta, pero aún incompleta. Indica correctamente si un jugador no tiene asistencias, aunque devuelve nulo en lugar de 0, lo cual es desafortunado.

Pero sigue siendo una solución parcial porque si un jugador no tiene ningún gol para un equipo, tampoco verá ninguna asistencia para esa combinación de jugador y equipo.

Esto utiliza una subconsulta como una tabla virtual que agrega asistencias por jugador y equipo, y la combinación externa izquierda de la subconsulta es lo que hace que arroje un resultado si hay goles, pero no asistencias.

select
    p.id as player_id
    , p.last_name
    , count(g.game_id) as goals
    , a.assists
from players p
inner join goals g on p.id = g.player_id
left join (
    select
        assists.player_id
        , goals.team_id
        , count(assists.id) as assists
    from assists
    inner join goals on assists.goal_id = goals.id
    group by player_id, team_id, assists.id
) a
on g.player_id = a.player_id and g.team_id = a.team_id
where g.team_id = 1
group by player_id, last_name, g.team_id

Esa consulta devuelve estos resultados:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     2 |       1 |
|  3 | Messier   |     1 |       1 |
+----+-----------+-------+---------+

Ejecute esto para el equipo 2 y obtendrá los siguientes resultados, lo que indica que Lemieux no tiene asistencias para el equipo 2, pero no arroja ningún resultado para los otros dos jugadores, que no tienen asistencias ni goles para el equipo 2:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  2 | Lemieux   |     1 |    null |
+----+-----------+-------+---------+

Finalmente, ejecútelo para el equipo 3 y obtendrá los siguientes resultados, lo que indica que Messier no tiene ninguna asistencia para el equipo 3. Pero falta Gretzky, a pesar de que tiene una asistencia para el equipo 3, porque no tiene cualquier objetivo para el equipo 3. Entonces la solución no está completa:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  3 | Messier   |     1 |    null |
+----+-----------+-------+---------+