棘手的 MySQL 视图

Tricky MySQL view

我发现在 MySQL 中创建视图非常困难,希望有人能帮助我。这是我的数据库的架构:

CREATE DATABASE football;

CREATE TABLE `team` (
  `name` varchar(15) PRIMARY KEY NOT NULL
  );
  
CREATE TABLE `season` (
   `name` char(9) PRIMARY KEY NOT NULL,
   `begin` date,
   `end` date);

CREATE TABLE `game` (
  `id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
  `Date` date DEFAULT NULL,
  `HomeTeam` varchar(15) NOT NULL,
  `AwayTeam` varchar(15) NOT NULL,
  `FTHG` int DEFAULT NULL,           (full time home goal)
  `FTAG` int DEFAULT NULL,           (full time away goal)
  `FTR` char(1) DEFAULT NULL,
  `HTHG` int DEFAULT NULL,
  `HTAG` int DEFAULT NULL,     
  `HTR` char(1) DEFAULT NULL,
  `H_S` int DEFAULT NULL,
  `A_S` int DEFAULT NULL,
  `HST` int DEFAULT NULL,
  `AST` int DEFAULT NULL,
  `HC` int DEFAULT NULL,
  `AC` int DEFAULT NULL,
  `HF` int DEFAULT NULL,
  `AF` int DEFAULT NULL,
  `HY` int DEFAULT NULL,
  `AY` int DEFAULT NULL,
  `HR` int DEFAULT NULL,
  `AR` int DEFAULT NULL,
  `season` char(9),
  FOREIGN KEY (HomeTeam) REFERENCES team(name),
  FOREIGN KEY (AwayTeam) REFERENCES team(name),
  FOREIGN KEY (season) REFERENCES season(name),
  CHECK (HomeTeam != AwayTeam)
);

该数据库收集了一系列足球比赛和每场比赛的许多特征,以及所有球队和赛季。 由于这种观点 (),我能够生成每个赛季的积分、进球数和失球数:

CREATE VIEW stats AS 
    (SELECT season,team,sum(TGS) TGS,sum(TGC) TGC,sum(pts) pts 
    FROM (SELECT season, HomeTeam team, FTHG TGS, FTAG TGC, 
    CASE WHEN FTHG > FTAG THEN 3 WHEN FTHG=FTAG THEN 1 ELSE 0 END pts 
    FROM game UNION ALL SELECT season, AwayTeam team, FTAG TGS, FTHG TGC, 
    CASE WHEN FTAG > FTHG THEN 3 WHEN FTAG=FTHG THEN 1 ELSE 0 END pts FROM game) games 
    GROUP BY season,team);

结果如下:

SELECT * FROM stats;

View 列依次为:赛季、球队、TGS(球队得分)、TGC(球队失球)

太好了,但我现在需要的是生成排名。理想情况下,我想要如下内容:

Team,19,18,17,16,15,14        (years)
Juventus,1,1,1,1,1,1          (came first each year)
Inter,2,4,4,7,4,8
Atalanta,3,3,7,4,13,17
Lazio,4,8,5,5,8,3
Roma,5,6,3,2,3,2
Milan,6,5,6,6,7,10
Napoli,7,2,2,3,2,5
Sassuolo,8,11,11,10,6,12
Verona,9,,19,,,13

一个主要的困难是,如您所见,排名来自第 14 年(2014-2015 赛季)。因此,此数据不存在于数据库中。虽然这是一件坏事,但是否可以在视图中对其进行硬编码?我总是需要每场比赛前一年的数据,所以添加旧游戏只会重现问题...... 此外,应排除当前季节(在示例中,将当前季节视为 2020-2021)。 感谢任何帮助或建议!

备注

我知道数据库结构可能不是最好的,但我现在必须坚持使用它...

为什么不只计算当前视图中每个球队/赛季的排名。现在您可以根据需要加入任何级别(和任何赛季)。

如果您需要上一年的排名,我们可以在后续表达式中使用 LAG 来做到这一点,或者只是根据与年份相关的一些表达式进行连接。

注意 select 列表中的 RANK 表达式。

The fiddle

建议(针对MySQL 8.0+):

CREATE VIEW stats AS
  SELECT season, team
       , sum(TGS) TGS, sum(TGC) TGC, sum(pts) pts
       , RANK() OVER (PARTITION BY season ORDER BY SUM(pts) DESC) AS rnk
    FROM (
           SELECT season, HomeTeam team, FTHG TGS, FTAG TGC
                , CASE WHEN FTHG > FTAG THEN 3 WHEN FTHG = FTAG THEN 1 ELSE 0 END pts
             FROM game
            UNION ALL
           SELECT season, AwayTeam team, FTAG TGS, FTHG TGC
                , CASE WHEN FTAG > FTHG THEN 3 WHEN FTAG = FTHG THEN 1 ELSE 0 END pts
             FROM game
         ) games
   GROUP BY season, team
;