Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Probleme beim korrekten Zählen mit einem Join

Ich denke, der einfachste Ansatz für das, was Sie zu tun versuchen, besteht darin, nur korrelierte Unterabfragen zu verwenden.

Das erste Beispiel unten gibt also die gesuchten Ergebnisse zurück . Sie könnten es leicht ändern, um die Reihen mit null Toren und Assists auszuschließen.

Es verwendet den team_id-Wert in jeder Unterabfrage, aber Sie können diesen wie gezeigt mit einer Variablen oder einem Parameter bereitstellen, sodass Sie den Wert nur einmal angeben müssen:

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

Für Mannschaft 1:

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

Für Team 2:

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

Für Team 3:

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

Epilog

Aus der Perspektive, dies mit weniger Unterabfragen und/oder mit aggregierten Abfragen zu versuchen, treten beim ersten Versuch einige Probleme auf.

Ein Problem besteht darin, dass Ihre Abfrage wahrscheinlich nicht richtig funktioniert, wenn Sie nicht alle Felder in Ihre group by aufnehmen -Klausel, obwohl MySQL Sie darüber nicht beschweren wird wie (die meisten?) anderen Datenbanken.

Da Aufzeichnungen sowohl in Ihren Assists- als auch in Spielertabellen nur indirekt über die Tortabelle mit den Teams in Verbindung stehen, ist es ziemlich schwierig, mit nur einer Abfrage eine unabhängige Zusammenfassung von Toren und Assists zu erhalten.

Zur Veranschaulichung hatten andere frühe Antworten darauf, einschließlich meines ersten schnellen Versuchs, ein paar Probleme:

  • Wenn ein Spieler Vorlagen für ein Team, aber keine Tore für dieses Team hatte, konnten die Abfragen keine Ergebnisse für diese Kombination aus Spieler und Team zurückgeben. Die Ergebnisse waren unvollständig.

  • Wenn ein Spieler Tore für ein Team hatte, aber keine Vorlagen für dieses Team hatte, würden die Abfragen immer noch eine positive Zahl für Vorlagen zurückgeben, obwohl sie null hätten zurückgeben sollen. Die Ergebnisse waren tatsächlich falsch, nicht nur unvollständig .

Direkt darunter ist eine etwas korrektere, aber immer noch unvollständige Lösung. Es zeigt korrekt an, ob ein Spieler keine Assists hat, obwohl es null statt 0 zurückgibt, was unglücklich ist.

Aber es ist immer noch eine Teillösung, denn wenn ein Spieler keine Tore für ein Team hat, werden Sie immer noch keine Vorlagen für diese Kombination aus Spieler und Team sehen.

Dabei wird eine Unterabfrage als virtuelle Tabelle verwendet, die Vorlagen pro Spieler und Team zusammenfasst, und der Left Outer Join der Unterabfrage sorgt dafür, dass ein Ergebnis zurückgegeben wird, wenn es Tore, aber keine Vorlagen gibt.

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

Diese Abfrage gibt diese Ergebnisse zurück:

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

Führen Sie dies für Team 2 aus, und Sie erhalten diese nächsten Ergebnisse, die darauf hinweisen, dass Lemieux keine Vorlagen für Team 2 hat, aber überhaupt keine Ergebnisse für die anderen beiden Spieler zurückgibt, die keine Vorlagen und keine Tore für Team 2 haben:

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

Führen Sie es schließlich für Team 3 aus, und Sie erhalten diese nächsten Ergebnisse, die darauf hinweisen, dass Messier keine Vorlagen für Team 3 hat. Aber Gretzky fehlt, obwohl er eine Vorlage für Team 3 hat, weil er keine hat alle Ziele für Team 3. Die Lösung ist also nicht vollständig:

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