2014-05-05 10 views
5

Obecnie osiągam wynik poniżej, używając tabeli o nazwie league_standing i aktualizując ją po każdym meczu. Chciałbym móc wykonać jedno zapytanie względem tabeli matches.Jak podsumować kolumny za pomocą klucza obcego, który znajduje się w dwóch kolumnach?

enter image description here

Teams grać ze sobą dwa razy, zarówno w kraju jak i na wyjeździe. Zauważ, jak team_id jest w dwóch kolumnach home_team_id i away_team_id

+----------------------------------+ 
|    Matches    | 
+----------------------------------+ 
| id        | 
| league_id (FK League)   | 
| season_id (FK Season)   | 
| home_team_id (FK Team)   | 
| away_team_id (FK Team)   | 
| home_score      | 
| away_score      | 
| confirmed      | 
+----------------------------------+ 

Oto co próbowałem, ale nie powiodło się:

select team.name, HomePoints + AwayPoints points 
from team join (
    select team.id, 
     sum(case when home.home_score > home.away_score then 3 
      when home.home_score = home.away_score then 1 else 0 end) HomePoints, 
     sum(case when away.away_score > away.home_score then 3 else 0 end) AwayPoints 
    from team 
    join matches home on team.id = home.home_team_id 
    join matches away on team.id = away.away_team_id 
    WHERE home.league_id = 94 
     AND home.season_id = 82 
     AND home.confirmed IS NOT NULL 
    group by id 
) temp on team.id = temp.id 
order by points desc; 

To daje mi źle punkty:

enter image description here

i ten daje mi poprawny wynik ligowych pozycji gospodarzy tylko

SELECT * FROM 
(
    SELECT team.name, home_team_id AS team_id, 
     COUNT(*) AS played, 
     SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS won, 
     SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS lost, 
     SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) AS drawn, 
     SUM(home_score) AS goalsFor, 
     SUM(away_score) AS goalsAgainst, 
     SUM(home_score - away_score) AS goalDifference, 
     SUM((CASE WHEN home_score > away_score THEN 3 WHEN home_score = away_score THEN 1 ELSE 0 END)) AS points 
    FROM matches 
    INNER JOIN team ON matches.home_team_id = team.id 
    WHERE league_id = 94 
     AND season_id = 82 
     AND confirmed IS NOT NULL 
    GROUP BY home_team_id 
UNION 
    SELECT team.name, away_team_id AS team_id, 
     COUNT(*) AS played, 
     SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS won, 
     SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS lost, 
     SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) as drawn, 
     SUM(away_score) AS goalsFor, 
     SUM(home_score) AS goalsAgainst, 
     SUM(away_score - home_score) AS goalDifference, 
     SUM((CASE WHEN away_score > home_score THEN 3 WHEN away_score = home_score THEN 1 ELSE 0 END)) AS points 
    FROM matches 
    INNER JOIN team ON matches.away_team_id = team.id 
    WHERE league_id = 94 
     AND season_id = 82 
     AND confirmed IS NOT NULL 
    GROUP BY away_team_id 
) x 
GROUP BY team_id 
ORDER BY points DESC; 

enter image description here

Jeśli to pomoże, moje schematu bazy danych:

enter image description here

Utknąłem! Mam nadzieję, że możesz pomóc.

+1

Nie rób tego. Jedną z zasad normalizacji baz danych jest nie zapisywanie wartości obliczonych. Zawsze możesz zaprezentować wyniki, uruchamiając zapytanie na innych stołach. –

+0

@DanBracuk Więc lepiej byłoby uruchomić kwerendę wybierającą w dopasowaniach, a następnie użyć PHP do obliczenia klasyfikacji? – Jonathan

Odpowiedz

1

Chciałbym obliczyć wyniki z domu i na wyjeździe dla każdej drużyny, a następnie wykonać agregację. Poniższe zapytanie powinno zrobić to, czego potrzebujesz. Aby uzyskać nazwę zespołu, musisz dołączyć do wyników przy stole drużynowym. Składnia działa dla PostgreSQL, może trzeba będzie coś zmienić dla mysql.

select team_id, count(*) as P, sum(W) as W, sum(D) as D, sum(L) as L, sum(GF) as GF, sum(GA) as GA, sum(GD) as GD, sum(PTS) as PTS from (
select home_team_id as team_id,  
     case when home_score > away_score then 1 
      else 0 end as W, 
     case when home_score = away_score then 1 
      else 0 end as D, 
     case when home_score < away_score then 1 
      else 0 end as L, 
     home_score as GF, 
     away_score as GA, 
     home_score-away_score as GD, 
     case when home_score > away_score then 3 
      when home_score = away_score then 1 
      else 0 end as PTS    
from matches 
where league_id = 94 and season_id = 82 and confirmed is not null 
union all 
select away_team_id as team_id,  
     case when home_score < away_score then 1 
      else 0 end as W, 
     case when home_score = away_score then 1 
      else 0 end as D, 
     case when home_score > away_score then 1 
      else 0 end as L, 
     away_score as GF, 
     home_score as GA, 
     away_score-home_score as GD, 
     case when home_score < away_score then 3 
      when home_score = away_score then 1 
      else 0 end as PTS    
from matches 
where league_id = 94 and season_id = 82 and confirmed is not null 
) as results 
group by team_id 
order by pts DESC,gd DESC,gf DESC; 

Nawiasem mówiąc, nie uważam, że przechowywanie wyników w tabeli i aktualizowanie ich po każdym meczu jest złym pomysłem. Przeliczanie zawsze tych samych wyników jest czymś, czego należy unikać, zwłaszcza jeśli jest wielu użytkowników, którzy są zainteresowani konsultacją rangi.

+0

Dzięki! Myślę, że pozostanę przy stole LeagueStanding, ale chcę zaimplementować funkcję pokazującą rankingi Last x Games, które będą dynamiczne przez cały sezon, więc wykorzystam to! – Jonathan

+0

Jak dodać zamówienie i limit do tego zapytania, jeśli Unia nie zezwala na to? Powiedz, że chcę uzyskać ranking na podstawie poprzednich 5 gier? – Jonathan

+0

Jeśli chcesz obliczyć pozycję na podstawie niektórych gier, nie potrzebujesz klauzuli limitu. Musisz filtrować dopasowania z konkretnym warunkiem w klauzuli where, na przykład ... gdzie ... i potwierdzone nie jest puste i ( między i ) Jeśli chcesz obliczyć ostatnie gry w samym zapytaniu, musisz wstawić dodatkowe podkwerendy do klauzuli where obu podkwerend. Proponuję tego nie robić, ale najpierw obliczyć interwał daty meczów, w których jesteś zainteresowany, a następnie dodać prosty warunek w klauzulach where. – maxvv

Powiązane problemy