如何在同一个table中正确组织历史数据?

How to properly organize historical data in the same table?

主要机构及问题

我正在处理 football 场比赛的数据库,该数据库按以下结构组织:

Country -> Competition -> Season -> Data

问题的基本问题是我不太确定我的数据库模式是否正确。

解释一下数据结构

主要"problem"是每个Data按特定季节分组,让我们考虑国家England:

Country | Competition    | Season    |
England | Premier League | 2017/2018 |
England | Premier League | 2016/2017 |
England | Premier League | 2015/2016 |
England | Premier League | 2014/2015 |
England | Premier League | 2013/2014 |

如您所见,England 有一个名为 Premier League 的比赛,分为 5 个赛季。

每个competition分为rounds,一个比赛可以由一个round组成,也可以由多个rounds.

组成

每个round可以分为groups,这取决于比赛类型,有些比赛不分组。

数据库结构

根据我对数据关系的解释,我配置了一个具有以下table:

的数据库结构
  1. 国家:包含所有可用的国家信息。
  2. 比赛:包含所有比赛详情。
  3. competition_seasons: 包含所有比赛赛季。
  4. competition_rounds:包含所有可用于比赛的回合。
  5. competition_groups:包含所有可参加比赛的组。
  6. league_ranking:包含了参加特定比赛的各队的所有排名。

数据库模式是这样的(我没有足够的代表来显示你需要的图像点击link):

enter image description here

数据库代码

-- -----------------------------------------------------
-- Table `mydb`.`country`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`country` (
  `id` INT NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `link` VARCHAR(255) NOT NULL,
  `iso` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`competition`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`competition` (
  `id` INT NOT NULL,
  `country_id` INT NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `link` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `id_idx` (`country_id` ASC),
  CONSTRAINT `FK_country_competition_country_id`
    FOREIGN KEY (`country_id`)
    REFERENCES `mydb`.`country` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`competition_seasons`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`competition_seasons` (
  `season_id` INT NOT NULL,
  `competition_id` INT NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `create_at` DATETIME NULL,
  `update_at` DATETIME NULL,
  INDEX `competition_id_idx` (`competition_id` ASC),
  PRIMARY KEY (`season_id`),
  CONSTRAINT `FK_competition_competition_seasons_competition_id`
    FOREIGN KEY (`competition_id`)
    REFERENCES `mydb`.`competition` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`competition_groups`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`competition_groups` (
  `group_id` INT NOT NULL,
  `competition_id` INT NOT NULL,
  `round_id` INT NOT NULL,
  INDEX `group_id_idx` (`group_id` ASC),
  INDEX `competition_id_idx` (`competition_id` ASC),
  INDEX `round_id_idx` (`round_id` ASC),
  CONSTRAINT `FK_group_competition_groups_group_id`
    FOREIGN KEY (`group_id`)
    REFERENCES `mydb`.`group` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `FK_competition_competition_groups_competition_id`
    FOREIGN KEY (`competition_id`)
    REFERENCES `mydb`.`competition` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `FK_round_competition_groups_round_id`
    FOREIGN KEY (`round_id`)
    REFERENCES `mydb`.`round` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`competition_rounds`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`competition_rounds` (
  `competition_id` INT NOT NULL,
  `round_id` INT NOT NULL,
  INDEX `competition_id_idx` (`competition_id` ASC),
  INDEX `round_id_idx` (`round_id` ASC),
  CONSTRAINT `FK_competition_competition_rounds_competition_id`
    FOREIGN KEY (`competition_id`)
    REFERENCES `mydb`.`competition` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `FK_round_competition_rounds_round_id`
    FOREIGN KEY (`round_id`)
    REFERENCES `mydb`.`round` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`league_ranking`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`league_ranking` (
  `id` INT NOT NULL,
  `position` INT NULL,
  `team_id` INT NULL,
  `season_id` INT NULL,
  `round_id` INT NULL,
  `competition_id` INT NULL,
  `group_id` INT NULL,
  `played_matches` INT NULL,
  `wins` INT NULL,
  `draws` INT NULL,
  `losses` INT NULL,
  `goals_for` INT NULL,
  `goals_against` INT NULL,
  `goals_difference` INT NULL,
  `points` INT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `FK_team_league_ranking_teamd_id`
    FOREIGN KEY (`id`)
    REFERENCES `mydb`.`team` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `FK_round_league_ranking_round_id`
    FOREIGN KEY (`id`)
    REFERENCES `mydb`.`round` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `FK_competition_league_ranking_competition_id`
    FOREIGN KEY (`id`)
    REFERENCES `mydb`.`competition` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `FK_group_league_ranking_group_id`
    FOREIGN KEY (`id`)
    REFERENCES `mydb`.`group` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

我的数据库模式是否适合商店的历史季节?

#1。首先,我不明白"competition_round" table的用法,这里你定义这个table有两列"competition_id"和"round_id"。反正你在"leage_ranking"table里面定义了"competition_id"和"round_id",所以,我建议不要再用多余的table来存储相同的数据。

#2。正如您提到的,您想要历史地存储数据,那么我假设交易量会减少,也可能不会。所以,我建议你去规范化 table。因为一天结束时您将要分析数据并对历史数据执行大量数据挖掘以提供适当的业务预期。

#3。除此之外,根据我的经验,它似乎是一个很好的数据模型。

Refer this link for understanding the database design patterns

假设

  • 一场比赛由1轮或多轮组成,
  • 一轮可选地由1个或多个组组成。

那我推荐

  • 一个 table 每个 'competition' 包含一行。
  • 一个 table 每个 'round' 包含一行。它应该包含一个 competition_id,它是 competition.id.
  • 的 FK
  • 一个 table 每个 'group' 包含一行。它应该包含一个 round_id,它是 round.id.
  • 的 FK

(等等)

这些是执行“1:many”映射的示例。 (注意“0 或更多”和 "optionally" 只是“1:many”的边缘情况,不需要额外的努力。)

我说 "one table" 因为 "vertical splitting" 很少是不必要的。只需将 "competition" 的所有属性放在一个 table 中。当某些属性(如'rounds')重复时,不能放在同一个table.

(table 名称 competition_rounds,虽然是描述性的,但让我感到困惑。)

一个相关的问题... 'competition' 的所有 'rounds' 都在一个国家播放吗?我在 competition 中看到 country_id;我想知道它是否应该移动到 rounds?