diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 13aec3e..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/2A/BDD/tp/s1/IMG_5011.HEIC b/2A/BDD/tp/s1/MCD.HEIC similarity index 100% rename from 2A/BDD/tp/s1/IMG_5011.HEIC rename to 2A/BDD/tp/s1/MCD.HEIC diff --git a/2A/BDD/tp/s1/requetesTP4-5-6.sql b/2A/BDD/tp/s1/requetesTP4-5-6.sql index 1ee212b..fdf7d46 100644 --- a/2A/BDD/tp/s1/requetesTP4-5-6.sql +++ b/2A/BDD/tp/s1/requetesTP4-5-6.sql @@ -1,4 +1,4 @@ --- \! clear +\! clear -- -- -- ? 1 - Écrire une fonction qui pour un match donné calcule le nombre de rebonds -- -- -- ? pris par les joueurs qui n’ont pas débuté la rencontre. Proposez deux versions, -- -- -- ? une utilisant les fonctions d’agrégation et une autre utilisant un curseur mais aucune fonction d’agrégation. @@ -230,180 +230,184 @@ -- END; -- $$ LANGUAGE plpgsql; --- -- ? 10 - Vérifier que l’équipe des Spurs a été meilleure à domicile qu’à l’extérieur pendant la saison 2021. +-- ? 10 - Vérifier que l’équipe des Spurs a été meilleure à domicile qu’à l’extérieur pendant la saison 2021. --- SELECT isBestAtHome(id, '2021') AS best_at_home --- FROM Team --- WHERE abbreviation = 'SAS'; +SELECT isBestAtHome(id, '2021') AS best_at_home +FROM Team +WHERE abbreviation = 'SAS'; --- -- ? 11 - Ecrire une fonction bestAtHome qui retourne une table avec les équipes (ids, abbréviations, noms et villes) --- -- ? qui ont gagné au moins autant de matchs à domicile qu’à l’extérieur lors de la saison passée en paramètre. +-- ? 11 - Ecrire une fonction bestAtHome qui retourne une table avec les équipes (ids, abbréviations, noms et villes) +-- ? qui ont gagné au moins autant de matchs à domicile qu’à l’extérieur lors de la saison passée en paramètre. --- CREATE OR REPLACE FUNCTION BestAtHome(GameSeason Game.season%TYPE) --- RETURNS TABLE(id Team.id%TYPE, abbreviation Team.abbreviation%TYPE, nom Team.nickname%TYPE, ville Team.city%TYPE) AS $$ --- BEGIN --- RETURN QUERY SELECT DISTINCT t.id, t.abbreviation, t.nickname, t.city --- FROM Team t --- WHERE isBestAtHome(t.id, GameSeason) = 1; --- END; --- $$ LANGUAGE plpgsql; - --- -- ? 12 - Quelles équipes ont gagné au moins autant de matchs à domicile qu’à l’extérieur en 2021? - --- SELECT BestAtHome(2021); - --- -- ? 13 - Ecrire une fonction qui retourne un booléen indiquant si une équipe donnée à gagner au moins autant de matchs à --- -- ? domiciles qu’à l’extérieur pendant au moins n saisons consécutives, où n est un paramètre de la fonction. --- -- ? Cette fonction devra lever une exception personnalisée si n n’est pas une valeur possible. - --- CREATE OR REPLACE FUNCTION isBestAtHomeDuring(nbSeason numeric) RETURNS numeric AS $$ --- DECLARE --- home_wins integer; --- away_wins integer; --- BEGIN --- SELECT COUNT(*) INTO home_wins --- FROM GAME g, Team t --- WHERE g.idHomeTeam = t.id AND isBestAtHome(t.id, g.season) = 1; - --- SELECT COUNT(*) INTO away_wins --- FROM GAME g, Team t --- WHERE g.idVisitorTeam = t.id AND isBestAtHome(t.id, g.season) = 0; - --- IF (home_wins >= away_wins) THEN --- RETURN 1; --- ELSE --- RETURN 0; --- END IF; --- END; --- $$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION BestAtHome(GameSeason Game.season%TYPE) +RETURNS TABLE(id Team.id%TYPE, abbreviation Team.abbreviation%TYPE, nom Team.nickname%TYPE, ville Team.city%TYPE) AS $$ +BEGIN + RETURN QUERY SELECT DISTINCT t.id, t.abbreviation, t.nickname, t.city + FROM Team t + WHERE isBestAtHome(t.id, GameSeason) = 1; +END; +$$ LANGUAGE plpgsql; --- CREATE OR REPLACE FUNCTION isBestAtHomeDuring(nbSeason numeric) RETURNS numeric AS $$ --- DECLARE --- home_wins integer; --- away_wins integer; --- BEGIN --- SELECT COUNT(*) INTO home_wins --- FROM GAME g, Team t --- WHERE g.idHomeTeam = t.id AND isBestAtHome(t.id, g.season) = 1; +-- ? 12 - Quelles équipes ont gagné au moins autant de matchs à domicile qu’à l’extérieur en 2021? --- SELECT COUNT(*) INTO away_wins --- FROM GAME g, Team t --- WHERE g.idVisitorTeam = t.id AND isBestAtHome(t.id, g.season) = 0; +SELECT BestAtHome(2021); --- IF (home_wins >= away_wins) THEN --- RETURN 1; --- ELSE --- RETURN 0; --- END IF; --- END; --- $$ LANGUAGE plpgsql; +-- ? 13 - Ecrire une fonction qui retourne un booléen indiquant si une équipe donnée à gagner au moins autant de matchs à +-- ? domiciles qu’à l’extérieur pendant au moins n saisons consécutives, où n est un paramètre de la fonction. +-- ? Cette fonction devra lever une exception personnalisée si n n’est pas une valeur possible. -CREATE OR REPLACE FUNCTION isBestAtHomeDuring(teamID Team.id%TYPE, n integer) RETURNS boolean AS $$ +CREATE OR REPLACE FUNCTION isBestAtHomeDuring(teamID Team.id%TYPE, n integer) RETURNS integer AS $$ DECLARE home_wins integer; away_wins integer; - consecutive_seasons integer[]; + consecutive_seasons integer; BEGIN -- Vérifier que n est une valeur valide (n doit être supérieur ou égal à 1) IF n < 1 THEN RAISE EXCEPTION 'La valeur de n doit être d''au moins 1.'; END IF; - -- Initialiser le tableau des saisons avec des victoires à domicile - consecutive_seasons := ARRAY[]::integer[]; - -- Compter le nombre de saisons SELECT COUNT(DISTINCT season) INTO consecutive_seasons FROM Game WHERE idHomeTeam = teamID OR idVisitorTeam = teamID; - -- Itérer sur les saisons + -- Vérifier si l'équipe a gagné au moins autant de matchs à domicile qu'à l'extérieur pour n saisons consécutives FOR i IN 1..consecutive_seasons - n + 1 LOOP - -- Vérifier si l'équipe a gagné au moins autant de matchs à domicile qu'à l'extérieur pendant n saisons consécutives - home_wins := ( - SELECT COUNT(*) - FROM GAME g - WHERE g.season >= i - AND g.season <= i + n - 1 - AND g.idHomeTeam = teamID - AND g.ptsHome > g.ptsAway - ); - - away_wins := ( - SELECT COUNT(*) - FROM GAME g - WHERE g.season >= i - AND g.season <= i + n - 1 - AND g.idVisitorTeam = teamID - AND g.ptsAway > g.ptsHome - ); - - -- Si l'équipe a gagné au moins autant de matchs à domicile qu'à l'extérieur pendant n saisons consécutives, retourner vrai + SELECT COUNT(*) INTO home_wins + FROM Game + WHERE season BETWEEN i AND i + n - 1 + AND idHomeTeam = teamID + AND ptsHome > ptsAway; + + SELECT COUNT(*) INTO away_wins + FROM Game + WHERE season BETWEEN i AND i + n - 1 + AND idVisitorTeam = teamID + AND ptsAway > ptsHome; + IF home_wins >= away_wins THEN - RETURN true; + RETURN 1; END IF; END LOOP; - -- Si l'équipe n'a pas gagné au moins autant de matchs à domicile qu'à l'extérieur pendant n saisons consécutives, retourner faux - RETURN false; + RETURN 0; END; $$ LANGUAGE plpgsql; -SELECT isBestAtHomeDuring('1610612737', 2021); +SELECT isBestAtHomeDuring('1610612737', 1) AS best_at_home_during_one_seasons; --- -- ? 14 - Y a t’il des équipes qui ont gagné au moins autant de matchs à domicile qu’à l’extérieur --- -- ? pendant 2 saisons consécutives ? Pendant 3 saisons consécutives ? +-- ? 14 - Y a t’il des équipes qui ont gagné au moins autant de matchs à domicile qu’à l’extérieur +-- ? pendant 2 saisons consécutives ? Pendant 3 saisons consécutives ? +SELECT isBestAtHomeDuring('1610612737', 2) AS best_at_home_during_two_seasons; +SELECT isBestAtHomeDuring('1610612737', 3) AS best_at_home_during_three_seasons; --- -- ? 15 - Écrire une fonction qui calcule l’id de l’équipe ayant le meilleur pourcentage moyen de paniers --- -- ? à 3 points d’une saison donnée. --- CREATE OR REPLACE FUNCTION idTeam3Points(GameSeason Game.season%TYPE) RETURNS numeric AS $$ --- DECLARE --- idTeam Team.id%TYPE; --- BEGIN --- SELECT t.id INTO idTeam --- FROM Team t, GameDetail gd, Game g --- WHERE gd.idTeam = t.id AND gd.idGame = g.id AND g.season = GameSeason AND gd.threePointsPrctage >= ALL(SELECT threePointsPrctage --- FROM GameDetail gd1 --- WHERE gd1.idTeam = t.id); --- RETURN idTeam; --- END; --- $$ LANGUAGE plpgsql; +-- ? 15 - Écrire une fonction qui calcule l’id de l’équipe ayant le meilleur pourcentage moyen de paniers +-- ? à 3 points d’une saison donnée. --- -- ? 16 - Utiliser cette fonction pour afficher la meilleure équipe (abbréviation, nom et ville) de la saison 2021 en pourcentage moyen de paniers à 3 points +CREATE OR REPLACE FUNCTION idTeam3Points(GameSeason numeric) RETURNS character varying AS $$ +DECLARE + bestTeamID character varying; +BEGIN + SELECT INTO bestTeamID gd.idTeam + FROM GameDetail gd, Game g + WHERE gd.idGame = g.id AND g.season = GameSeason + GROUP BY gd.idTeam + ORDER BY AVG(gd.threePointsPrctage) DESC + LIMIT 1; + + RETURN bestTeamID; +END; +$$ LANGUAGE plpgsql; --- SELECT t.id, t.abbreviation, t.nickname, t.city --- FROM Team t --- WHERE idTeam3Points('2021') = t.id; --- -- ? 17 - Écrire une fonction qui calcule combien de paniers à trois points ont été marqué par un joueur donné, pendant une saison donnée. +-- ? 16 - Utiliser cette fonction pour afficher la meilleure équipe (abbréviation, nom et ville) de la saison 2021 en pourcentage moyen de paniers à 3 points + +SELECT abbreviation, nickname, city +FROM Team +WHERE id = idTeam3Points('2021'); + +-- ! charge infiniment + +-- ? 17 - Écrire une fonction qui calcule combien de paniers à trois points ont été marqué par un joueur donné, pendant une saison donnée. --- CREATE OR REPLACE FUNCTION idTeam3Points(idPlayer Player.id%TYPE , GameSeason Game.season%TYPE) RETURNS numeric AS $$ --- DECLARE --- idTeam Team.id%TYPE; --- BEGIN --- SELECT t.id INTO idTeam --- FROM Team t, GameDetail gd, Game g, Player p --- WHERE gd.idTeam = t.id AND gd.idGame = g.id AND p.id = idPlayer AND g.season = GameSeason AND gd.threePointsPrctage >= ALL(SELECT threePointsPrctage --- FROM GameDetail gd1 --- WHERE gd1.idTeam = t.id); --- RETURN idTeam; --- END; --- $$ LANGUAGE plpgsql; --- -- ? 18 - Écrire une fonction qui calcule l’id du joueur ayant marqué le plus de paniers à trois points pendant une saison donnée. +CREATE OR REPLACE FUNCTION count3pointsbyplayer(idP character varying, GameSeason numeric) RETURNS numeric AS $$ +DECLARE + totalThreePoints numeric; +BEGIN + SELECT SUM(gd.threePointsMade) + INTO totalThreePoints + FROM GameDetail gd + JOIN Game g ON gd.idGame = g.id + WHERE gd.idPlayer = idP AND g.season = GameSeason; + + RETURN totalThreePoints; +END; +$$ LANGUAGE plpgsql; + +SELECT count3pointsbyplayer('203932', '2021'); + + +-- ? 18 - Écrire une fonction qui calcule l’id du joueur ayant marqué le plus de paniers à trois points pendant une saison donnée. + +CREATE OR REPLACE FUNCTION idPlayerMost3Points(GameSeason Game.season%TYPE) RETURNS Player.id%TYPE AS $$ +DECLARE + best_player_id Player.id%TYPE; +BEGIN + SELECT gd.idPlayer INTO best_player_id + FROM GameDetail gd + JOIN Game g ON gd.idGame = g.id + WHERE g.season = GameSeason + GROUP BY gd.idPlayer + ORDER BY SUM(gd.threePointsMade) DESC + LIMIT 1; + + RETURN best_player_id; +END; +$$ LANGUAGE plpgsql; + +SELECT idPlayerMost3Points('2021'); + + +-- ? 19 - En utilisant les fonctions précédement créées, écrire un bloc anonyme qui affiche pour chaque saison, par ordre chronologique, +-- ? le nom du joueur ayant marqué le plus de paniers à trois points ainsi que le nombres de paniers à trois points marqués. + +DO $$ +DECLARE + season_value Game.season%TYPE; + player_id Player.id%TYPE; + total_3_points numeric; +BEGIN + FOR season_value IN (SELECT DISTINCT season FROM Game ORDER BY season) LOOP + player_id := idPlayerMost3Points(season_value); + total_3_points := count3PointsByPlayer(player_id, season_value); + RAISE NOTICE 'Saison %: Joueur ID %, Nombre de paniers à trois points : %', season_value, player_id, total_3_points; + END LOOP; +END; +$$; +-- ? 20 - Ce calcul est très long. Pour effectuer un calcul plus efficace, nous allons créer une table supplémentaire permettant de stocker des statistiques. +-- ? Créer la table Stats(season, player, threePoints) contenant le nombre de paniers à trois points marqués par chaque joueur pendant une saison et +-- ? la remplir avec les données contenues dans GameDetail. +-- ? △! Penser à éliminer les valeurs NULL. --- -- ? 19 - En utilisant les fonctions précédement créées, écrire un bloc anonyme qui affiche pour chaque saison, par ordre chronologique, --- -- ? le nom du joueur ayant marqué le plus de paniers à trois points ainsi que le nombres de paniers à trois points marqués. +CREATE TABLE Stats ( + season numeric, + player varchar(10), + threePoints numeric +); --- -- ? 20 - Ce calcul est très long. Pour effectuer un calcul plus efficace, nous allons créer une table supplémentaire permettant de stocker des statistiques. --- -- ? Créer la table Stats(season, player, threePoints) contenant le nombre de paniers à trois points marqués par chaque joueur pendant une saison et --- -- ? la remplir avec les données contenues dans GameDetail. --- -- ? △! Penser à éliminer les valeurs NULL. \ No newline at end of file +-- Insertion des données de GameDetail dans la table Stats +INSERT INTO Stats (season, player, threePoints) + SELECT g.season, gd.idPlayer, SUM(gd.threePointsMade) + FROM GameDetail gd, Game g + WHERE gd.idGame = g.id AND gd.threePointsMade IS NOT NULL + GROUP BY g.season, gd.idPlayer;