-- 1. Nombre de violons loués par des élèves.
SELECT COUNT(*) FROM louer WHERE instrument = (
	SELECT id FROM instrument WHERE designation = 'Violon'
);

-- 2. Numéros, noms et prénoms des élèves louant plus de 2 instruments.
SELECT e.num, e.nom, e.prenom
FROM louer l
INNER JOIN eleve e ON e.num = l.eleve
GROUP BY e.num
HAVING COUNT(*) > 1;

-- 3. Pour chaque instrument (id, designation), plus vieil élève (nom, prénom) suivant un cours de cet instrument.
WITH plusVieuxEleves AS (
	SELECT MAX(e.age) age, s.instrument FROM suivre s
	INNER JOIN eleve e ON e.num = s.eleve
	GROUP BY s.instrument
)
SELECT i.id, i.designation, e.nom, e.prenom FROM suivre s
INNER JOIN instrument i ON i.id = s.instrument
INNER JOIN eleve e ON e.num = s.eleve
INNER JOIN plusVieuxEleves p ON p.age = e.age AND s.instrument = s.instrument;

-- 4. Définir la fonction PL/pgSQL total qui prend en paramètre un numéro d’élève et retourne le montant total qu’il doit régler à l’école de musique (pour les cours et la location des instruments) sachant qu’une inscription à un cours correspond à 30h de cours par an
CREATE OR REPLACE FUNCTION total(eleve_num INT)
RETURNS INT AS $$
DECLARE
    totalCours INT;
	totalInstruments INT;
BEGIN
	SELECT COALESCE(SUM(n.tarifHoraire * 30), 0) INTO STRICT totalCours FROM suivre s
	INNER JOIN niveau n ON n.niveau = s.niveau
	WHERE s.eleve = eleve_num;

	SELECT COALESCE(SUM(i.tarifLocation), 0) INTO STRICT totalInstruments FROM louer l
	INNER JOIN instrument i ON i.id = l.instrument
	WHERE l.eleve = eleve_num;

	RETURN totalCours + totalInstruments;
END;
$$ LANGUAGE plpgsql;

-- 5. Utiliser la fonction total pour afficher le montant dû par chaque élève (num, nom, prénom)
SELECT num, nom, prenom, total(num) FROM eleve;

-- 6.  Mettre à jour le tarif de location des instruments loués plus de 10 fois, en augmentant leur tarif de 50€.
-- Un GROUP BY ne s'associe pas vraiment avec un update :/
/*UPDATE instrument i SET tarifLocation = tarifLocation + 50
FROM louer l
WHERE l.instrument = i.id
GROUP BY i.id
HAVING COUNT(*) > 10;*/
UPDATE instrument SET tarifLocation = tarifLocation + 50
WHERE id IN (
	SELECT instrument FROM louer
	GROUP BY instrument
	HAVING COUNT(*) > 10
);

/*DO $$
DECLARE
    curs cursor FOR SELECT i.id FROM louer l
		INNER JOIN instrument i ON l.instrument = i.id
		GROUP BY i.id
		HAVING COUNT(*) > 10
		FOR UPDATE;
	instrument_courant INT;
BEGIN
    open curs;
    fetch curs into instrument_courant;
    while found loop
        UPDATE instrument SET tarifLocation = tarifLocation + 50 WHERE CURRENT OF curs;
        fetch curs into instrument_courant;
    end loop;
    close curs;
END;
$$ LANGUAGE plpgsql;*/
DO $$
DECLARE
    curs cursor FOR SELECT instrument FROM louer
	GROUP BY instrument
	HAVING COUNT(*) > 10;
	instrument_courant INT;
BEGIN
    open curs;
    fetch curs into instrument_courant;
    while found loop
        UPDATE instrument SET tarifLocation = tarifLocation + 50 WHERE instrument = instrument_courant;
        fetch curs into instrument_courant;
    end loop;
    close curs;
END;
$$ LANGUAGE plpgsql;

-- 7. Créer une vue ElevesPiano rassemblant toutes les informations sur les élèves (nom, prénom, âge, adresse et niveau) des élèves qui suivent des cours de piano
CREATE VIEW ElevesPiano AS
SELECT e.nom, e.prenom, e.age, e.rue || e.codePostal || e.ville adresse, s.niveau
FROM suivre s
INNER JOIN eleve e ON e.num = s.eleve
WHERE s.instrument = (SELECT id FROM instrument WHERE designation = 'Piano');

-- 8. Créer un utilisateur rh pouvant créer des rôles.
CREATE USER rh CREATEROLE;

-- 9. Donner à l’utilisateur rh l’autorisation de consulter, ajouter, supprimer et modifier des lignes de la table Professeur.
GRANT CONNECT ON DATABASE dbclfreville2 TO rh;
GRANT SELECT, INSERT, DELETE, UPDATE ON Professeur TO rh;

-- 10. L’administrateur de la base de données décide de changer de fonctionnement : au lieu d’avoir un seul compte rh utilisé par tous les RH de l’école de musique, il veut créer un compte pour chacun d’entre eux, mais qu’ils aient tous les droits de rh. (Le rôle rh ne devra plus être utilisable directement.)
--REVOKE LOGIN TO rh; -- Instruction seulement pour une base de données précise
ALTER ROLE rh RESET LOGIN;
CREATE USER ldupond PASSWORD 'azerty';
GRANT rh TO ldupond;

-- *quelques expérimentations sur la performance de ces requêtes*
EXPLAIN ANALYZE SELECT id FROM restaurant WHERE min_price >= ALL (SELECT min_price FROM restaurant); -- 178 / 21
EXPLAIN ANALYZE SELECT id FROM restaurant ORDER BY min_price DESC LIMIT 1; -- 5
EXPLAIN ANALYZE SELECT id FROM restaurant ORDER BY min_price DESC FETCH FIRST 1 ROWS ONLY; -- 5
EXPLAIN ANALYZE SELECT id FROM restaurant WHERE min_price = (SELECT MAX(min_price) FROM restaurant); -- 6

/*for cle, valeur in dictionnaire:
	if valeur >= local_max:
		local_max = valeur
		local_max_cle = cle*/

