You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IUT/2A/BDD/tp/s1/requetesTP4-5-6.sql

409 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

-- \! clear
-- -- -- ? 1 - Écrire une fonction qui pour un match donné calcule le nombre de rebonds
-- -- -- ? pris par les joueurs qui nont pas débuté la rencontre. Proposez deux versions,
-- -- -- ? une utilisant les fonctions dagrégation et une autre utilisant un curseur mais aucune fonction dagrégation.
-- -- CREATE OR REPLACE FUNCTION calcul_rebonds(match Game.id%TYPE) RETURNS integer AS $$
-- -- DECLARE
-- -- sumRebounds integer;
-- -- BEGIN
-- -- SELECT sum(gd.rebounds) INTO sumRebounds
-- -- FROM GameDetail gd, Game g
-- -- WHERE g.id = match AND gd.idGame = g.id AND gd.startPosition is NULL;
-- -- RETURN sumRebounds;
-- -- END;
-- -- $$ LANGUAGE plpgsql;
-- -- SELECT calcul_rebonds('22100979');
-- -- -- CREATE FUNCTION
-- -- -- calcul_rebonds
-- -- -- ----------------
-- -- -- 32
-- -- -- (1 row)
-- -- CREATE OR REPLACE FUNCTION calcul_rebonds_curs(match Game.id%TYPE) RETURNS GameDetail.rebounds%TYPE AS $$
-- -- DECLARE
-- -- sumRebounds GameDetail.rebounds%TYPE := 0;
-- -- rbs GameDetail.rebounds%TYPE := 0;
-- -- curs cursor FOR SELECT rebounds
-- -- FROM GameDetail
-- -- WHERE idGame = match AND startPosition is NULL AND rebounds is NOT NULL;
-- -- BEGIN
-- -- OPEN curs;
-- -- FETCH curs INTO rbs;
-- -- WHILE FOUND LOOP
-- -- sumRebounds = sumRebounds + rbs;
-- -- FETCH curs INTO rbs;
-- -- END LOOP;
-- -- CLOSE curs;
-- -- RETURN sumRebounds;
-- -- END;
-- -- $$ LANGUAGE plpgsql;
-- -- SELECT calcul_rebonds_curs('22100979');
-- -- -- CREATE FUNCTION
-- -- -- calcul_rebonds_curs
-- -- -- ---------------------
-- -- -- 32
-- -- -- (1 row)
-- -- -- ? 2 - Vérifier que vos deux versions retournent les mêmes résultats en affichant le nombre total de rebonds
-- -- -- ? pris par les joueurs nayant pas débuté la rencontre pour tous les matchs ayant eu lieu le 12 mars 2022.
-- -- SELECT calcul_rebonds(id)
-- -- FROM Game
-- -- WHERE dateGame = '2022-03-12';
-- -- -- calcul_rebonds
-- -- -- ----------------
-- -- -- 39
-- -- -- 20
-- -- -- 43
-- -- -- 40
-- -- -- 41
-- -- -- 25
-- -- -- 24
-- -- -- (7 rows)
-- -- SELECT calcul_rebonds_curs(id)
-- -- FROM Game
-- -- WHERE dateGame = '2022-03-12';
-- -- -- calcul_rebonds_curs
-- -- -- ---------------------
-- -- -- 39
-- -- -- 20
-- -- -- 43
-- -- -- 40
-- -- -- 41
-- -- -- 25
-- -- -- 24
-- -- -- (7 rows)
-- -- -- ? 3 - Écrire une fonction qui calcule la même chose mais pour les joueurs ayant débuté la rencontre,
-- -- -- ? autrement dit qui calcule, pour un match donné, le nombre de rebonds pris par les joueurs ayant débuté la rencontre.
-- -- CREATE OR REPLACE FUNCTION calcul_rebonds_t(match Game.id%TYPE) RETURNS integer AS $$
-- -- DECLARE
-- -- sumRebounds integer;
-- -- BEGIN
-- -- SELECT sum(gd.rebounds) INTO sumRebounds
-- -- FROM GameDetail gd, Game g
-- -- WHERE g.id = match AND gd.idGame = g.id AND gd.startPosition is NOT NULL;
-- -- IF sumRebounds is NULL THEN
-- -- RETURN 0;
-- -- END IF;
-- -- RETURN sumRebounds;
-- -- END;
-- -- $$ LANGUAGE plpgsql;
-- -- SELECT calcul_rebonds_t('22100979');
-- -- -- CREATE FUNCTION
-- -- -- calcul_rebonds_t
-- -- -- ------------------
-- -- -- 57
-- -- -- (1 row)
-- -- CREATE OR REPLACE FUNCTION calcul_rebonds_curs_t(match Game.id%TYPE) RETURNS GameDetail.rebounds%TYPE AS $$
-- -- DECLARE
-- -- sumRebounds GameDetail.rebounds%TYPE := 0;
-- -- rbs GameDetail.rebounds%TYPE := 0;
-- -- curs cursor FOR SELECT rebounds
-- -- FROM GameDetail
-- -- WHERE idGame = match AND startPosition is NOT NULL AND rebounds is NOT NULL;
-- -- BEGIN
-- -- OPEN curs;
-- -- FETCH curs INTO rbs;
-- -- WHILE FOUND LOOP
-- -- sumRebounds = sumRebounds + rbs;
-- -- FETCH curs INTO rbs;
-- -- END LOOP;
-- -- CLOSE curs;
-- -- RETURN sumRebounds;
-- -- END;
-- -- $$ LANGUAGE plpgsql;
-- -- SELECT calcul_rebonds_curs_t('22100979');
-- -- -- CREATE FUNCTION
-- -- -- calcul_rebonds_curs_t
-- -- -- -----------------------
-- -- -- 57
-- -- -- (1 row)
-- -- SELECT calcul_rebonds_t('10300004');
-- -- SELECT calcul_rebonds_curs_t('10300004');
-- -- -- ? 4 - Trouver le match (abréviation des équipes et date) pendant lequel les joueurs
-- -- -- ? ayant débuté la rencontre ont réalisé le plus de rebonds.
-- -- SELECT t1.abbreviation, t2.abbreviation, g.dateGame, calcul_rebonds_t(g.id)
-- -- FROM Game g, Team t1, Team t2
-- -- WHERE g.idHomeTeam = t1.id AND g.idVisitorTeam = t2.id AND calcul_rebonds_t(g.id) = (SELECT max(calcul_rebonds_t(id))
-- -- FROM Game);
-- -- -- abbreviation | abbreviation | dategame | calcul_rebonds_t
-- -- -- --------------+--------------+------------+------------------
-- -- -- POR | DEN | 2019-05-03 | 101
-- -- -- (1 row)
-- -- -- ? 5 - Y a til des matchs pour lesquels les données sur les rebonds sont incohérentes?
-- -- -- ? Vérifier en comparant les valeurs obtenus grâce aux fonctions précédentes avec les valeurs contenues dans la table Game.
-- -- -- ! SELECT t1.abbreviation, t2.abbreviation, g.dateGame, (calcul_rebonds_t(g.id) + calcul_rebonds(g.id)) as fct, g.reboundsHome, g.reboundsAway
-- -- -- ! FROM Game g, Team t1, Team t2
-- -- -- ! WHERE g.idHomeTeam = t1.id AND g.idVisitorTeam = t2.id AND calcul_rebonds_t(g.id) = (SELECT max(calcul_rebonds_t(id))
-- -- -- ! FROM Game);
-- -- -- ? 6 - Écrire une fonction qui pour un match et une équipe donnée calcule le total des points des joueurs de cet équipe pendant le match,
-- -- -- ? à partir des données contenues dans la table GameDetail.
-- -- CREATE OR REPLACE FUNCTION PtsTotJoueur(match Game.id%TYPE, team Team.id%TYPE)
-- -- RETURNS integer as $$
-- -- DECLARE total integer;
-- -- BEGIN
-- -- SELECT sum(points) INTO total
-- -- FROM GameDetail
-- -- WHERE idTeam = team AND idGame = match AND points IS NOT NULL;
-- -- IF total is NULL THEN
-- -- RETURN 0;
-- -- END IF;
-- -- RETURN total;
-- -- END;
-- -- $$ LANGUAGE plpgsql;
-- -- SELECT PtsTotJoueur('22101006','1610612741');
-- -- -- ? 7 - Utiliser cette fonction pour vérifier si les valeurs ptsHome et ptsAway de la table Game sont correctes.
-- -- SELECT g.id AS idGame, t.id AS idTeam, g.ptsHome, g.ptsAway, PtsTotJoueur(g.id, g.idHomeTeam) AS ptsHome1, PtsTotJoueur(g.id, g.idVisitorTeam) AS ptsAway2
-- -- FROM GAME g, Team t
-- -- WHERE g.idVisitorTeam = t.id;
-- -- -- ? 8 - Quelle table contient des données incorrectes/incomplètes ? Game ou GameDetail ? Vérifier grâce aux résultats officiels des matchs.
-- -- ? 9 - Ecrire une fonction isBestAtHome qui retourne un booléen indiquant si une équipe donnée a
-- -- ? gagné au moins autant de matchs à domicile quà lextérieur lors de la saison passée en paramètre.
-- CREATE OR REPLACE FUNCTION isBestAtHome(IdTeam Team.id%TYPE, GameSeason Game.season%TYPE) RETURNS numeric AS $$
-- DECLARE
-- home_wins integer;
-- away_wins integer;
-- BEGIN
-- SELECT COUNT(*) INTO home_wins
-- FROM GAME g
-- WHERE g.season = GameSeason AND g.idHomeTeam = IdTeam AND g.ptsHome > g.ptsAway;
-- SELECT COUNT(*) INTO away_wins
-- FROM GAME g
-- WHERE g.season = GameSeason AND g.idVisitorTeam = IdTeam AND g.ptsAway > g.ptsHome;
-- IF (home_wins >= away_wins) THEN
-- RETURN 1;
-- ELSE
-- RETURN 0;
-- END IF;
-- END;
-- $$ LANGUAGE plpgsql;
-- -- ? 10 - Vérifier que léquipe des Spurs a été meilleure à domicile quà lextérieur pendant la saison 2021.
-- 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à lexté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à lexté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à lexté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 nest 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 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 isBestAtHomeDuring(teamID Team.id%TYPE, n integer) RETURNS boolean AS $$
DECLARE
home_wins integer;
away_wins 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
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
IF home_wins >= away_wins THEN
RETURN true;
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;
END;
$$ LANGUAGE plpgsql;
SELECT isBestAtHomeDuring('1610612737', 2021);
-- -- ? 14 - Y a til des équipes qui ont gagné au moins autant de matchs à domicile quà lextérieur
-- -- ? pendant 2 saisons consécutives ? Pendant 3 saisons consécutives ?
-- -- ? 15 - Écrire une fonction qui calcule lid de léquipe ayant le meilleur pourcentage moyen de paniers
-- -- ? à 3 points dune 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;
-- -- ? 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 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.
-- 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 lid du joueur ayant marqué le plus de paniers à trois points pendant une saison donnée.
-- -- ? 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.
-- -- ? 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.