sql >> Database teknologi >  >> RDS >> Mysql

Problemer med at få korrekt tal med en joinforbindelse

Jeg tror, ​​at den mest ligetil tilgang til det, du forsøger at gøre, er blot at bruge korrelerede underforespørgsler.

det første eksempel lige nedenfor returnerer de resultater, du leder efter . Du kan nemt ændre det for at udelukke rækkerne med nul mål og assists.

Den bruger team_id-værdien i hver underforespørgsel, men du kan levere den med en variabel eller parameter, som vist, så du kun behøver at angive værdien én gang:

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
 

For hold 1:

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

For hold 2:

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

For hold 3:

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

Epilog

Set ud fra et forsøg på at gøre dette med færre underforespørgsler og/eller med samlede forespørgsler, har du et par problemer i gang med dit første forsøg.

Et problem er, at din forespørgsel sandsynligvis ikke vil fungere korrekt, hvis du ikke inkluderer alle felterne i din group by klausul, selvom MySQL ikke vil brokke dig over det, ligesom (de fleste?) andre databaser vil.

Fordi rekorder i både dine assists og spillertabeller kun er indirekte relateret til hold gennem måltabellen, er det temmelig svært at få en uafhængig opgørelse af både mål og assists med kun én forespørgsel.

Som en slags illustration havde andre tidlige svar på dette, inklusive mit første hurtige skud på det, et par problemer:

  • Hvis en spiller havde assists for et hold, men ikke havde nogen mål for det hold, kunne forespørgslerne ikke returnere nogen resultater for den pågældende spiller og holdkombination. Resultaterne var ufuldstændige.

  • Hvis en spiller havde mål for et hold, men ikke havde assists for det hold, ville forespørgslerne stadig returnere et positivt tal for assists, når de skulle have returneret nul. Resultaterne var faktisk forkerte, ikke bare ufuldstændige .

Lige nedenfor er en lidt mere korrekt, men stadig ufuldstændig løsning. Det angiver korrekt, om en spiller ikke har nogen assists, dog ved at returnere null i stedet for 0, hvilket er uheldigt.

Men det er stadig en delvis løsning, for hvis en spiller ikke har nogen mål for et hold, vil du stadig ikke se nogen assists for den spiller og holdkombinationen.

Dette bruger en underforespørgsel som en virtuel tabel, der samler assists pr. spiller og hold, og den venstre ydre joinforbindelse til underforespørgslen er det, der får den til at returnere et resultat, hvis der er mål, men ingen 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
 

Denne forespørgsel returnerer disse resultater:

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

Kør dette for hold 2, og du får disse næste resultater, hvilket indikerer, at Lemieux ikke har nogen assists til hold 2, men ikke returnerer nogen resultater overhovedet for de to andre spillere, som ikke har nogen assists og ingen mål for hold 2:

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

Kør det endelig for hold 3, og du får disse næste resultater, der indikerer, at Messier ikke har nogen assists til hold 3. Men Gretzky mangler, selvom han har en assist til hold 3, fordi han ikke har eventuelle mål for hold 3. Så løsningen er ikke komplet:

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


  1. PHP PDO indsæt flere (10000+) samme rækker ved hjælp af bindParam. God øvelse?

  2. Spring JPA + skifter dynamisk datakilden mellem skemaer i postgresql

  3. GPL og libmysqlclient

  4. Introduktion til Multi-Statement Table-Valued Functions (MSTVF) i SQL Server