CREATE TABLE "user" ( 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 ( id SERIAL PRIMARY KEY, score INTEGER NOT NULL, playtime TIME NOT NULL, date DATE NOT NULL, user_id INT NOT NULL, FOREIGN KEY (user_id) REFERENCES "user" ); 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 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 WHERE user_id = NEW.user_id GROUP BY user_id; 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 TRIGGER game_played AFTER INSERT ON game FOR EACH ROW EXECUTE FUNCTION update_user_scores();