sql >> Databasteknik >  >> RDS >> Mysql

Problem med att få korrekt räkning med en join

Jag tror att den enklaste inställningen till det du försöker göra är att bara använda korrelerade underfrågor.

det första exemplet precis nedan returnerar resultaten du letar efter . Du kan enkelt ändra den för att utesluta raderna med noll mål och assist.

Den använder team_id-värdet i varje underfråga, men du kan förse det med en variabel eller parameter, som visas, så att du bara behöver ange värdet en gång:

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 lag 1:

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

För lag 2:

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

För lag 3:

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

Epilog

Ur perspektivet att försöka göra detta med färre underfrågor och/eller med sammanställda frågor, har du ett par problem på gång med ditt första försök.

Ett problem är att din fråga förmodligen inte kommer att fungera korrekt om du inte inkluderar alla fält i din group by klausul även om MySQL inte kommer att gnälla på dig om det som (de flesta?) andra databaser kommer att göra.

Dessutom, eftersom rekord i både dina assist- och spelartabeller endast är indirekt relaterade till lag genom måltabellen, är det ganska svårt att få en oberoende sammanställning av både mål och assist med bara en fråga.

Som en typ av illustration hade andra tidiga svar på detta, inklusive min första snabba bild på det, ett par problem:

  • Om en spelare hade assist för ett lag, men inte hade några mål för det laget, kunde frågorna inte returnera några resultat för den spelaren och lagkombinationen. Resultaten var ofullständiga.

  • Om en spelare hade mål för ett lag, men inte hade några assist för det laget, skulle frågorna fortfarande returnera ett positivt tal för assist när de borde ha returnerat noll. Resultaten var faktiskt felaktiga, inte bara ofullständiga .

Strax nedan finns en lite mer korrekt, men fortfarande ofullständig lösning. Den indikerar korrekt om en spelare inte har några assist, om än genom att returnera null istället för 0 vilket är olyckligt.

Men det är fortfarande en dellösning eftersom om en spelare inte har några mål för ett lag, kommer du fortfarande inte att se några assist för den spelaren och lagkombinationen.

Detta använder en underfråga som en virtuell tabell som samlar assist per spelare och lag, och den vänstra yttre kopplingen till underfrågan är det som gör att den returnerar ett resultat om det finns mål, men inga assist.

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

Den frågan returnerar dessa resultat:

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

Kör detta för lag 2, och du får följande resultat, vilket indikerar att Lemieux inte har några assist för lag 2, men ger inga resultat alls för de andra två spelarna, som inte har några assist och inga mål för lag 2:

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

Slutligen, kör det för lag 3, och du får följande resultat, vilket indikerar att Messier inte har några assist för lag 3. Men Gretzky saknas, även om han har en assist för lag 3, eftersom han inte har några mål för team 3. Så lösningen är inte komplett:

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



  1. Frågar DAU/MAU över tid (dagligen)

  2. Hur man skapar dynamisk sql för med sys_refcursor i oracle

  3. Hur infogar jag flera rader med en främmande nyckel med en CTE i Postgres?

  4. PHP SQL Views-räknare med PDO prepare()