From d174f7440843417ca247b583f37720eab44f73db Mon Sep 17 00:00:00 2001 From: j-weissen Date: Tue, 13 Dec 2022 09:50:33 +0100 Subject: [PATCH] optimized schema --- backend/README.md | 31 +++++++--- backend/db/initScripts/_createSchema.sql | 75 ++++++++++++++++++---- backend/db/initScripts/loadMockData.sql | 79 ++++++++++++------------ 3 files changed, 125 insertions(+), 60 deletions(-) diff --git a/backend/README.md b/backend/README.md index bbb4279..97e5f5f 100644 --- a/backend/README.md +++ b/backend/README.md @@ -3,7 +3,8 @@ ```mermaid erDiagram user { - string name PK + serial id PK + string name } game { @@ -11,17 +12,33 @@ erDiagram int score time playtime date date - string username FK + int user_id FK } - user ||--O{ game : "played" - - user_data { - string username PK + user_scores { + int user_id PK int highscore int total_score int total_playtime int average_score int games_played } -``` \ No newline at end of file + + lb_highscore { + int rank + int user_id + int highscore + } + + lb_total_playtime { + int rank + int user_id + time total_playtime + } + + user ||--O{ game : "played" + user ||--|| user_scores : "" +``` +`lb_highscore` and `lb_total_playtime` are views querying the `user_scores` table. + +A trigger function on insert to the `user` table creates a new row in `user_scores`. Everytime a new `game` is inserted, the row is updated. \ No newline at end of file diff --git a/backend/db/initScripts/_createSchema.sql b/backend/db/initScripts/_createSchema.sql index ee4cb61..d203328 100644 --- a/backend/db/initScripts/_createSchema.sql +++ b/backend/db/initScripts/_createSchema.sql @@ -1,5 +1,16 @@ CREATE TABLE "user" ( - username VARCHAR(32) PRIMARY KEY + id SERIAL PRIMARY KEY, + name VARCHAR(32) +); + +CREATE TABLE user_scores ( + user_id INT PRIMARY KEY REFERENCES "user", + highscore INT NOT NULL DEFAULT 0, + total_score INT NOT NULL DEFAULT 0, + total_playtime TIME NOT NULL DEFAULT '00:00:00', + average_score INT NOT NULL DEFAULT 0, + games_played INT NOT NULL DEFAULT 0, + FOREIGN KEY (user_id) REFERENCES "user" ); CREATE TABLE game ( @@ -7,26 +18,64 @@ CREATE TABLE game ( score INTEGER NOT NULL, playtime TIME NOT NULL, date DATE NOT NULL, - username VARCHAR(32) NOT NULL, - FOREIGN KEY (username) REFERENCES "user" + user_id INT NOT NULL, + FOREIGN KEY (user_id) REFERENCES "user" ); -CREATE VIEW user_data AS ( +CREATE VIEW lb_highscore AS ( + SELECT row_number() OVER (ORDER BY highscore DESC) AS rank, user_id, highscore FROM user_scores ORDER BY rank +); + +CREATE VIEW lb_total_playtime AS ( + SELECT row_number() OVER (ORDER BY total_playtime DESC) AS rank, user_id, total_playtime AS total_playtime FROM user_scores ORDER BY rank +); + +CREATE OR REPLACE FUNCTION insert_new_user_scores() + RETURNS TRIGGER + LANGUAGE plpgsql AS +$$ + BEGIN + INSERT INTO user_scores (user_id) VALUES (NEW.id); + RETURN NEW; + END; +$$; + +CREATE TRIGGER user_added + AFTER INSERT ON "user" + FOR EACH ROW +EXECUTE FUNCTION insert_new_user_scores(); + +CREATE OR REPLACE FUNCTION update_user_scores() + RETURNS TRIGGER + LANGUAGE plpgsql AS +$$ +DECLARE + row user_scores%ROWTYPE; +BEGIN SELECT - username, + user_id, max(score) AS highscore, sum(score) AS total_score, sum(playtime) AS total_playtime, avg(score) AS average_score, count(*) AS games_played + INTO row FROM game - GROUP BY username -); + WHERE user_id = NEW.user_id + GROUP BY user_id; -CREATE VIEW lb_highscore AS ( - SELECT row_number() OVER (ORDER BY max(score) DESC) AS rank, username, max(score) AS highscore FROM game GROUP BY username ORDER BY rank -); + UPDATE user_scores SET + highscore = row.highscore, + total_score = row.total_score, + total_playtime = row.total_playtime, + average_score = row.average_score, + games_played = row.games_played + WHERE user_id = row.user_id; + RETURN NEW; +END +$$; -CREATE VIEW lb_total_playtime AS ( - SELECT row_number() OVER (ORDER BY sum(playtime) DESC) AS rank, username, sum(playtime) AS total_playtime FROM game GROUP BY username ORDER BY rank -); +CREATE TRIGGER game_played + AFTER INSERT ON game + FOR EACH ROW +EXECUTE FUNCTION update_user_scores(); diff --git a/backend/db/initScripts/loadMockData.sql b/backend/db/initScripts/loadMockData.sql index b6c2676..7735cc9 100644 --- a/backend/db/initScripts/loadMockData.sql +++ b/backend/db/initScripts/loadMockData.sql @@ -1,41 +1,40 @@ -insert into "user" (username) values ('dpettus0'); -insert into "user" (username) values ('egreetland1'); -insert into "user" (username) values ('smontford2'); -insert into "user" (username) values ('idagwell3'); -insert into "user" (username) values ('lgagan4'); -insert into "user" (username) values ('acarmont5'); -insert into "user" (username) values ('kjermyn6'); -insert into "user" (username) values ('dokieran7'); -insert into "user" (username) values ('pdrinkel8'); -insert into "user" (username) values ('amelladew9'); +insert into "user" (name) values ('dpettus0'); +insert into "user" (name) values ('egreetland1'); +insert into "user" (name) values ('smontford2'); +insert into "user" (name) values ('idagwell3'); +insert into "user" (name) values ('lgagan4'); +insert into "user" (name) values ('acarmont5'); +insert into "user" (name) values ('kjermyn6'); +insert into "user" (name) values ('dokieran7'); +insert into "user" (name) values ('pdrinkel8'); -insert into game (username, score, playtime, date) values ('dpettus0', 74, '19:59', '2022-07-19'); -insert into game (username, score, playtime, date) values ('dpettus0', 86, '20:32', '2022-11-24'); -insert into game (username, score, playtime, date) values ('dpettus0', 68, '10:41', '2022-03-24'); -insert into game (username, score, playtime, date) values ('egreetland1', 39, '5:55', '2022-06-01'); -insert into game (username, score, playtime, date) values ('egreetland1', 20, '9:23', '2022-03-12'); -insert into game (username, score, playtime, date) values ('egreetland1', 28, '23:45', '2022-04-01'); -insert into game (username, score, playtime, date) values ('smontford2', 44, '18:43', '2022-06-24'); -insert into game (username, score, playtime, date) values ('smontford2', 92, '14:54', '2022-11-06'); -insert into game (username, score, playtime, date) values ('smontford2', 73, '0:45', '2022-07-26'); -insert into game (username, score, playtime, date) values ('idagwell3', 27, '2:49', '2022-02-03'); -insert into game (username, score, playtime, date) values ('idagwell3', 26, '2:32', '2022-07-19'); -insert into game (username, score, playtime, date) values ('idagwell3', 12, '17:03', '2022-04-25'); -insert into game (username, score, playtime, date) values ('lgagan4', 6, '8:49', '2021-12-03'); -insert into game (username, score, playtime, date) values ('lgagan4', 22, '22:27', '2022-03-02'); -insert into game (username, score, playtime, date) values ('lgagan4', 94, '1:04', '2022-10-19'); -insert into game (username, score, playtime, date) values ('acarmont5', 2, '2:14', '2022-04-06'); -insert into game (username, score, playtime, date) values ('acarmont5', 21, '17:18', '2022-06-03'); -insert into game (username, score, playtime, date) values ('acarmont5', 33, '16:01', '2022-02-02'); -insert into game (username, score, playtime, date) values ('kjermyn6', 27, '7:03', '2022-02-06'); -insert into game (username, score, playtime, date) values ('kjermyn6', 62, '0:45', '2022-11-15'); -insert into game (username, score, playtime, date) values ('kjermyn6', 12, '8:54', '2022-06-29'); -insert into game (username, score, playtime, date) values ('dokieran7', 63, '16:01', '2022-11-05'); -insert into game (username, score, playtime, date) values ('dokieran7', 29, '0:46', '2022-10-01'); -insert into game (username, score, playtime, date) values ('dokieran7', 67, '1:27', '2022-09-29'); -insert into game (username, score, playtime, date) values ('pdrinkel8', 84, '10:37', '2021-12-18'); -insert into game (username, score, playtime, date) values ('pdrinkel8', 14, '19:14', '2022-01-31'); -insert into game (username, score, playtime, date) values ('pdrinkel8', 21, '19:04', '2022-03-08'); -insert into game (username, score, playtime, date) values ('amelladew9', 46, '2:34', '2022-04-18'); -insert into game (username, score, playtime, date) values ('amelladew9', 78, '9:33', '2022-09-10'); -insert into game (username, score, playtime, date) values ('amelladew9', 82, '11:19', '2022-11-29'); \ No newline at end of file +insert into game (user_id, score, playtime, date) values ('1', 74, '19:59', '2022-07-19'); +insert into game (user_id, score, playtime, date) values ('1', 86, '20:32', '2022-11-24'); +insert into game (user_id, score, playtime, date) values ('1', 68, '10:41', '2022-03-24'); +insert into game (user_id, score, playtime, date) values ('2', 39, '5:55', '2022-06-01'); +insert into game (user_id, score, playtime, date) values ('2', 20, '9:23', '2022-03-12'); +insert into game (user_id, score, playtime, date) values ('2', 28, '23:45', '2022-04-01'); +insert into game (user_id, score, playtime, date) values ('2', 44, '18:43', '2022-06-24'); +insert into game (user_id, score, playtime, date) values ('3', 92, '14:54', '2022-11-06'); +insert into game (user_id, score, playtime, date) values ('3', 73, '0:45', '2022-07-26'); +insert into game (user_id, score, playtime, date) values ('3', 27, '2:49', '2022-02-03'); +insert into game (user_id, score, playtime, date) values ('4', 26, '2:32', '2022-07-19'); +insert into game (user_id, score, playtime, date) values ('4', 12, '17:03', '2022-04-25'); +insert into game (user_id, score, playtime, date) values ('4', 6, '8:49', '2021-12-03'); +insert into game (user_id, score, playtime, date) values ('4', 22, '22:27', '2022-03-02'); +insert into game (user_id, score, playtime, date) values ('5', 94, '1:04', '2022-10-19'); +insert into game (user_id, score, playtime, date) values ('5', 2, '2:14', '2022-04-06'); +insert into game (user_id, score, playtime, date) values ('5', 21, '17:18', '2022-06-03'); +insert into game (user_id, score, playtime, date) values ('6', 33, '16:01', '2022-02-02'); +insert into game (user_id, score, playtime, date) values ('6', 27, '7:03', '2022-02-06'); +insert into game (user_id, score, playtime, date) values ('6', 62, '0:45', '2022-11-15'); +insert into game (user_id, score, playtime, date) values ('7', 12, '8:54', '2022-06-29'); +insert into game (user_id, score, playtime, date) values ('7', 63, '16:01', '2022-11-05'); +insert into game (user_id, score, playtime, date) values ('7', 29, '0:46', '2022-10-01'); +insert into game (user_id, score, playtime, date) values ('8', 67, '1:27', '2022-09-29'); +insert into game (user_id, score, playtime, date) values ('8', 84, '10:37', '2021-12-18'); +insert into game (user_id, score, playtime, date) values ('8', 14, '19:14', '2022-01-31'); +insert into game (user_id, score, playtime, date) values ('9', 21, '19:04', '2022-03-08'); +insert into game (user_id, score, playtime, date) values ('9', 46, '2:34', '2022-04-18'); +insert into game (user_id, score, playtime, date) values ('9', 78, '9:33', '2022-09-10'); +insert into game (user_id, score, playtime, date) values ('9', 82, '11:19', '2022-11-29'); \ No newline at end of file