2014-05-05 53 views
5

目前,我正在使用名爲league_standing的表格實現以下結果,並在每次比賽結束後進行更新。我希望能夠處理表matches中的一個查詢。如何通過兩列中的外鍵來總結列?

enter image description here

Teams打對方兩次,均是主場還是客場。請注意如何team_id是在兩列home_team_idaway_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      | 
+----------------------------------+ 

這是我曾嘗試但失敗:

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; 

它讓我有錯誤之分:

enter image description here

而這一次只給我主場聯賽的正確結果

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

如果有幫助,我的數據庫模式:

enter image description here

我卡住了!希望你能幫助。

+1

不要這樣做。數據庫規範化的一個規則是不存儲計算值。您可以通過在其他表格上運行選擇查詢來始終顯示積分榜。 –

+0

@DanBracuk因此,對匹配運行選擇查詢並使用PHP計算排名會更好嗎? – Jonathan

回答

1

我會計算每個團隊的主客場結果,然後進行聚合。 以下查詢應該做你需要的。你只需要將結果與team表結合起來即可獲得團隊名稱。 該語法適用於PostgreSQL,可能需要爲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; 

順便說一句,我不認爲將結果存儲在表中並在每次匹配後更新它們是一個壞主意。 重新計算總是相同的結果是應該避免的,特別是如果有許多用戶有興趣諮詢排名。

+0

謝謝!我想我會堅持與LeagueStanding表,但我想實現一個功能,以顯示Last x Games的積分榜,這將在本賽季動態,所以將使用這個! – Jonathan

+0

如果Union不允許,您如何添加訂單並限制此查詢?假設我想根據前5場比賽獲得積分榜? – Jonathan

+0

如果你想基於某些遊戲計算站立位置,則不需要限制條款。您需要使用where子句中的特定條件過濾匹配項,例如, ...其中...並且確認不爲空(之間) 如果要計算在查詢本身中最後一個遊戲,則需要在兩個子查詢的where子句中插入附加的子查詢。 我建議不要這樣做,但首先計算您感興趣的匹配的日期間隔,然後在where子句中添加一個簡單的條件。 – maxvv