탁구 리그전(대회)을 개최하고 결과를 표시해주는 서비스를 만들기 위한 ERD 설계.
대회의 특성을 살펴보자면 많은 부수에 따른 리그(경기)들이 있고 그 리그 안에는 각각의 경기가 속하게 된다.
이 사진은 3부라는 리그 경기의 예선전이다. 여기에서 3등을 하게되면 예선 탈락, 1,2 등을 하게 되면 본선으로 가게된다.

이렇게 결과가 본선으로 가게되면 예선전에서는 풀리그 였지만 토너먼트로 경기의 특성이 바뀌고 남자 3부의 결과가 나오게 된다.

이런 특성을 가지고 있기에 대회, 경기, 게임 이 3단계로 구분을 하였고, 복식과 단체전을 커버하기 위해서 그룹테이블을 별도로 만들어 관리하였다.

탁구 리그전 서비스를 이용하는 사용자의 기본 정보를 관리한다. 인증 정보와 탁구 실력을 나타내는 rating(부수) 을 함께 저장하여 사용자 식별과 경기 매칭의 기준으로 활용한다.
CREATE TABLE user (
user_id BIGINT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
username VARCHAR(50) UNIQUE NOT NULL,
real_name VARCHAR(100) NOT NULL,
gender ENUM('MALE', 'FEMALE') NOT NULL,
birth_date DATE NOT NULL,
region VARCHAR(100),
phone_number VARCHAR(20),
rating INT DEFAULT 12 COMMENT '0: 선수부, 1~12: 1부~12부',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
탁구 대회의 최상위 개념으로 전체 이벤트 정보를 관리한다. 한 명의 주최자가 여러 대회를 만들 수 있으며, 하나의 대회는 여러 경기 단계(competition)를 포함할 수 있다.
CREATE TABLE tournament (
tournament_id BIGINT PRIMARY KEY AUTO_INCREMENT,
tournament_name VARCHAR(200) NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
location VARCHAR(200) NOT NULL,
organizer_id BIGINT NOT NULL,
entry_fee DECIMAL(10, 2) DEFAULT 0,
event_info TEXT COMMENT '경기 종목 정보',
prize_info TEXT COMMENT '시상 정보',
description TEXT,
status ENUM('DRAFT', 'REGISTRATION_OPEN', 'REGISTRATION_CLOSED', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED') DEFAULT 'DRAFT',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (organizer_id) REFERENCES user(user_id) ON DELETE RESTRICT
);
organizer_id의 ON DELETE RESTRICT로 주최자 삭제 방지
status로 대회 생명주기 관리
event_info와 prize_info는 TEXT 타입으로 자유롭게 작성 가능
tournament와 user를 연결하는 중간 테이블로, 누가 어느 대회에 참가했는지 기록한다. 참가 신청부터 최종 순위까지의 전체 과정을 추적한다.
CREATE TABLE tournament_participant (
participation_id BIGINT PRIMARY KEY AUTO_INCREMENT,
tournament_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
participation_status ENUM('REGISTERED', 'CONFIRMED', 'WITHDRAWN', 'DISQUALIFIED') DEFAULT 'REGISTERED',
final_rank INT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (tournament_id) REFERENCES tournament(tournament_id) ON DELETE RESTRICT,
FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE RESTRICT,
UNIQUE KEY unique_participation (tournament_id, user_id)
);
하나의 대회 안에서 진행되는 경기 단계를 관리한다. 예선전, 본선, 결승 토너먼트처럼 대회는 여러 단계로 구성될 수 있으며, 각 단계마다 다른 경기 방식과 참가 형식을 가질 수 있다.
CREATE TABLE competition (
competition_id BIGINT PRIMARY KEY AUTO_INCREMENT,
tournament_id BIGINT NOT NULL,
competition_name VARCHAR(200) NOT NULL COMMENT '예선, 본선, 결승 토너먼트 등',
competition_type ENUM('ROUND_ROBIN', 'SINGLE_ELIMINATION', 'DOUBLE_ELIMINATION', 'GROUP_STAGE') NOT NULL,
match_format ENUM('SINGLES', 'DOUBLES', 'TEAM') NOT NULL COMMENT '단식, 복식, 단체전',
competition_order INT NOT NULL COMMENT '대회 내 진행 순서',
has_groups BOOLEAN DEFAULT FALSE COMMENT '조 편성 여부',
players_per_group INT COMMENT '조별 인원수',
description TEXT,
status ENUM('SCHEDULED', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED') DEFAULT 'SCHEDULED',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (tournament_id) REFERENCES tournament(tournament_id) ON DELETE RESTRICT
);
조별 경기를 위한 그룹 정보를 관리한다. competition에서 has_groups가 TRUE일 때 사용되며, A조, B조와 같이 참가자를 나누어 조별 리그를 진행할 수 있다.
CREATE TABLE `group` (
group_id BIGINT PRIMARY KEY AUTO_INCREMENT,
competition_id BIGINT NOT NULL,
group_name VARCHAR(50) NOT NULL COMMENT 'A조, B조 등',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (competition_id) REFERENCES competition(competition_id) ON DELETE RESTRICT,
UNIQUE KEY unique_group (competition_id, group_name)
);
특정 조에 속한 참가자를 관리한다. 조별 리그에서 어떤 사용자가 어느 조에 배정되었는지, 조 내에서의 최종 순위는 어떻게 되었는지 기록한다.
CREATE TABLE group_participant (
group_participant_id BIGINT PRIMARY KEY AUTO_INCREMENT,
group_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
group_rank INT COMMENT '조 내 최종 순위',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (group_id) REFERENCES `group`(group_id) ON DELETE RESTRICT,
FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE RESTRICT,
UNIQUE KEY unique_group_participant (group_id, user_id)
);
실제 경기 정보를 저장한다. 두 팀(또는 두 명)이 대결하는 개별 경기의 일정, 결과, 세트 스코어를 관리하며, 토너먼트의 경우 대진표 구조도 표현한다.
CREATE TABLE `match` (
match_id BIGINT PRIMARY KEY AUTO_INCREMENT,
competition_id BIGINT NOT NULL,
group_id BIGINT COMMENT '조별 경기인 경우 조 ID',
match_round INT COMMENT '토너먼트의 경우 라운드 (8강=8, 4강=4, 결승=2)',
match_number INT COMMENT '같은 라운드 내 경기 번호',
court_number INT COMMENT '코트 번호',
status ENUM('SCHEDULED', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED', 'NO_SHOW') DEFAULT 'SCHEDULED',
winner_side ENUM('SIDE_A', 'SIDE_B', 'DRAW') COMMENT '승리 팀',
side_a_sets INT COMMENT 'A팀이 획득한 세트 수',
side_b_sets INT COMMENT 'B팀이 획득한 세트 수',
total_sets INT COMMENT '총 진행된 세트 수',
next_match_id BIGINT COMMENT '토너먼트에서 다음 라운드 경기',
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (competition_id) REFERENCES competition(competition_id) ON DELETE RESTRICT,
FOREIGN KEY (group_id) REFERENCES `group`(group_id) ON DELETE RESTRICT,
FOREIGN KEY (next_match_id) REFERENCES `match`(match_id) ON DELETE SET NULL
);
각 경기에 참여하는 선수들을 관리한다. 단식은 양쪽 1명씩, 복식은 2명씩, 단체전은 3명 이상이 참여하며, side로 양 팀을 구분하고 participant_order로 팀 내 순서를 관리힌다.
CREATE TABLE match_participant (
match_participant_id BIGINT PRIMARY KEY AUTO_INCREMENT,
match_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
side ENUM('SIDE_A', 'SIDE_B') NOT NULL,
participant_order INT COMMENT '복식이나 단체전에서 순서',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (match_id) REFERENCES `match`(match_id) ON DELETE RESTRICT,
FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE RESTRICT
);
캬