sql >> Database >  >> RDS >> Mysql

Problemen om de juiste telling te krijgen met een join

Ik denk dat de meest directe benadering van wat je probeert te doen is om gewoon gecorreleerde subquery's te gebruiken.

Dus het eerste voorbeeld net hieronder geeft de resultaten die u zoekt . Je zou het gemakkelijk kunnen aanpassen om de rijen met nul goals en assists uit te sluiten.

Het gebruikt de team_id-waarde in elke subquery, maar u kunt die leveren met een variabele of parameter, zoals weergegeven, zodat u de waarde maar één keer hoeft op te geven:

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

Voor team 1:

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

Voor team 2:

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

Voor team 3:

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

Epiloog

Als je dit probeert te doen met minder subquery's en/of met geaggregeerde zoekopdrachten, heb je een aantal problemen met je eerste poging.

Een probleem is dat uw zoekopdracht waarschijnlijk niet correct werkt als u niet alle velden in uw group by opneemt. clausule hoewel MySQL je daar niet over zal zeuren zoals (de meeste?) andere databases.

Omdat records in zowel je assist- als spelerstafels alleen indirect gerelateerd zijn aan teams via de doelpuntentafel, is het behoorlijk moeilijk om een ​​onafhankelijk overzicht te krijgen van beide goals en assists met slechts één vraag.

Ter illustratie:andere vroege antwoorden hierop, waaronder mijn eerste snelle poging, hadden een aantal problemen:

  • Als een speler assists had voor een team, maar geen goals voor dat team had, konden de zoekopdrachten geen resultaten opleveren voor die combinatie van speler en team. De resultaten waren onvolledig.

  • Als een speler doelpunten had voor een team, maar geen assists voor dat team, zouden de zoekopdrachten nog steeds een positief getal opleveren voor assists terwijl ze nul hadden moeten zijn. De resultaten waren eigenlijk verkeerd, niet alleen onvolledig .

Net hieronder is een iets meer correcte, maar nog steeds onvolledige oplossing. Het geeft correct aan of een speler geen assists heeft, zij het door null terug te geven in plaats van 0, wat jammer is.

Maar het is nog steeds een gedeeltelijke oplossing, want als een speler geen doelen voor een team heeft, zie je nog steeds geen assists voor die speler en teamcombinatie.

Dit gebruikt een subquery als een virtuele tabel die assists per speler en team verzamelt, en de linker buitenste join naar de subquery zorgt ervoor dat het een resultaat oplevert als er doelpunten zijn, maar geen assists.

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

Die zoekopdracht levert deze resultaten op:

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

Voer dit uit voor team 2 en je krijgt deze volgende resultaten, wat aangeeft dat Lemieux geen assists heeft voor team 2, maar helemaal geen resultaten geeft voor de andere twee spelers, die geen assists en geen goals hebben voor team 2:

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

Voer het ten slotte uit voor team 3 en je krijgt de volgende resultaten, wat aangeeft dat Messier geen assists heeft voor team 3. Maar Gretzky ontbreekt, ook al heeft hij wel een assist voor team 3, omdat hij geen assists heeft. alle doelen voor team 3. Dus de oplossing is niet compleet:

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



  1. Hoe Perl te gebruiken om een ​​mysql-wachtwoord te wijzigen

  2. Hoe kan ik alle sessies die verbinding maken met mijn Oracle-database beëindigen?

  3. hoe te gebruiken WHERE IN mysql opgeslagen procedure

  4. MySQL-verbinding op afstand mislukt met onbekende authenticatiemethode