Bonjour,
J'ai une table COURS dont voici la structure
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`id_categorie` smallint(5) unsigned NOT NULL,
`id_chapitre` mediumint(5) unsigned NOT NULL,
`titre` varchar(150) NOT NULL,
`description` text NOT NULL,
`youtube` varchar(100) NOT NULL,
En gros il s'agit d'une liste de cours répartis en catégorie (arithmétique, algèbre, géométrie,...), et chacune des catégories est elle même divisée en chapitre (calcul écrit, technique de calcul,...)
Je suis en train de programmer une page categorie.php contenant les 3 premiers cours de chaque chapitre dont l'id_categorie de ce tableau COURS est une valeur précise.
Concrêtement, id_categorie=1 correspond à la catégorie "Arithmétique", et sur cette page Arithmétique je veux afficher les 3 premiers cours de chaque chapitre appartenant à cette catégorie arithmétique.
Quelle est selon vous la méthode la plus optimale pour procéder ?
La solution la plus évidente serait de faire une requête de ce genre :
SELECT ... FROM Cours WHERE id_categorie=1 AND id_chapitre=1 LIMIT 3
Et de la répéter autant de fois qu'il y a de chapitre, en changeant donc à chaque fois l'id_chapitre concerné.
Mais j'ai peur que niveau performance ce ne soit pas efficace !
Sinon j'avais pensé à créer une table temporaire issue de la table Cours mais ne reprenant que les lignes dont id_categorie=1. Et puis à partir de cette table temporaire je ferais ce genre de requête.
SELECT ... FROM TMP_Arithmétique WHERE id_chapitre=1 LIMIT 3
Requête à également répéter autant de fois qu'il y a de chapitre différent...
Mais pareil, j'ai peur pour les performances car ca ne doit pas etre anodins de créer à chaque fois une table, et puis de faire toutes les requêtes sachant qu'il peut y avoir une vingtaine de chapitres.
Devrais-je m'orienter alors plutôt vers une vue matérialisée ? Mais dans ce cas la je dois prendre en compte le cout de la mise à jour de cette vue matérialisée...
Existe-t-il une solution plus simple à laquelle je n'aurais pas pensé ? Je vous serai très reconnaissant si vous pouviez m'éclairer, merci !
EDIT START
EDIT END
Alors il te faut trois tables: Categories, Chapitres et Cours.
// Categories
`id` integer NOT NULL AUTO_INCREMENT
...
// Chapitres
`id` integer NOT NULL AUTO_INCREMENT,
`categorie` integer NOT NULL
...
// Cours
`id` integer NOT NULL AUTO_INCREMENT
`chapitre` integer NOT NULL,
`titre` varchar(150) NOT NULL,
`description` text NOT NULL,
`youtube` varchar(100) NOT NULL,
Ensuite tu récupères 3 cours de chaques chapitre en utilisant une sous-requête:
SELECT *
FROM Cours
WHERE Cours.chapitre IN (SELECT Chapitres.id FROM Chapitres WHERE Chapitres.categorie = 1)
LIMIT 3
Je ne l'ai pas testé, mais de mémoire ça doit fonctionner.
Tu devrais pouvoir t'en sortir avec les fonctions GROUP_CONCAT , SUBSTRING_INDEX et FIND_IN_SET.
GROUP_CONCAT renvoie une liste des valeurs séparées par des virgules,
une liste pour chaque groupe généré par un GROUP BY
SUBSTRING_INDEX permet de tronquer la liste et de ne garder que les n premiers (ici n = 3)
FIND_IN_SET retourne la position d'un élément dans une liste (1 à N)
SELECT C.* FROM cours C WHERE FIND_IN_SET(C.id,
(SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY id ASC SEPARATOR ','), ',' ,3) FROM cours WHERE id_chapitre = C.id_chapitre GROUP BY id_chapitre)) > 0
Bonjour,
Pour commencer, je n'utiliserai pas la même structure de table.
J'opterai plus pour :
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent` int(11) unsigned NULL,
`titre` varchar(150) NOT NULL,
`description` text NOT NULL,
`youtube` varchar(100) NOT NULL,
Dans la colonne 'parent' tu laisse a null si c'est une catégorie ou tu mets l'id de la matiere si c'est une sous-matière.
Ensuite pour la page categories je ferais ça :
SELECT * FROM cours WHERE parent IS NULL;
Et je ferais un foreach
sur celle ci où j'effectuerai une nouvelle requete du type :
SELECT * FROM cours WHERE parent = :id LIMIT 3;
Ou sinon une requete globale et ensuite tu "parse" le résultat de ton tableau avec PHP ensuite :
SELECT a.titre as cat, b.titre as subcat FROM cours a, cours b WHERE b.parent = a.id;
Pas certain d'avoir compris.
C'est quoi un cours ? "Math", "Français", "Physique", ... ?
Ensuite si "Math" est un cours alors une catégorie c'est "arithmétique", "algèbre", "géométrie", ... ? Et chapitre c'est "calcul écrit", "technique de calcul", ... ?
Donc si j'ai compris un cours peut avoir plusieurs catégories et une catégorie peut avoir plusieurs chapitres. Et si cela est le cas alors tu as un problème de conception cars ta table fait que pour chaque cours il ne peut y avoir une seule catégorie et un seul chapitre.
Redis-moi si mon analyse est juste avant de te fournir la solution
@Axis: je n'ai pas trop compris ta solution, tu parles bien de la table COURS reprenant l'ensemble des cours ? Car chaque cours est obligatoirement lié à une et une seule catégorie et un seul chapitre, ce qui ne me semble pas possible dans ce que tu présentes. Si je laisse parent vide ca me donne simplement un cours orphelin. Désolé peut etre ca vient du fait que je me suis mal exprimé : x
@Twentyfour: désolé mon message n'était pas très bien expliqué, en fait un cours c'est par exemple "Comment calculer la pente de la fonction", donc c'est la logique inverse de ce que tu décris. Le site n'aborde que les math. Donc Math est divisé en catégorie (ce sont mes menus principaux), et chaque catégorie est divisée en chapitre, et chaque chapitre est divisé en cours, et ces cours sont donc repris dans le tableau en question. Ce qui fait que plusieurs cours appartiennent à un même chapitre, que plusieurs chapitres appartiennent à une meme catégorie, et que toutes les catégories appartiennent à maths. Un cours n'a qu'un seul chapitre et une seule catégorie, et un chapitre n'a qu'une seule catégorie. Voilà j'espère tu y verras plus claire :)