Page 1 sur 1

Problème php/mysql_query / select distinct

Posté : 21 sept. 2006, 00:54
par Karter
Bonjour tout le monde,

Je débute en php/mysql et je ne comprends pas pourquoi une partie de mon code ne s'execute pas. Je vous expose mon problème : J'ai installé un script php pour gérer mes vidéo et j'essaie de le remodeler de manière à obtenir une solution adaptée à mes besoins.

Dans une table qui contient toutes les informations sur mes video (realisateur, acteur, genre ...) j'ai une colonne appelée acteur dans laquelle figure la liste des principaux acteurs pour chaque film. Mon but étant de créer une liste de choix (balise select) permettant pour chaque acteur de sortir une liste complète des films dans lesquels celui ci joue. J'ai partiellement réussi mais la requête me fait aboutir à une liste de tous les acteurs présents dans la base de données. Je me retrouve donc avec pleins de doublons et qui plus est rien est classé alphabétiquement.

Voici la requête que j'envoie :

$requete=mysql_query("SELECT DISTINCT acteur FROM Film WHERE acteur != '' AND acteur!='0' ORDER BY acteur");

Théoriquement, cette requête permet d'afficher tous les champs de la colonne en excluant les doublons, si je ne me trompe pas ; or ça n'est pas le cas. Je pense que le problème vient du fait que pour chaque film, il y a plusieurs acteurs, donc plusieurs valeurs et que le serveur les compare entre elles au sein de chaque film mais pas au niveau de tous les films de la base.

Quelqu'un a-t-il une solution à me proposer ?

Merci d'avance.

Posté : 21 sept. 2006, 01:12
par graphistnet
Tu dis que la requête ne fonctionne pas mais qu'est ce qui ne fonctionne pas, tu as un message d'erreur?

Posté : 21 sept. 2006, 01:37
par Karter
Non la requête fonctionne mais partiellement, elle me récupère bien tous les acteurs de la base mais j'ai pleins de doublons.

Par ex : 3 films : piège de cristal, 6ème sens, armageddon. Bruce Willis joue dans les 3, la requête me sort 3 fois son nom donc une fois par film dans ma baliste alors que j'ai besoin de l'avoir qu'une seule fois. Ceci étant ça fonctionne bien puisque quand j'appuie sur n'importe quel des 3 Bruce Willis, ça me sort la liste ces 3 films qui sont rentrés dans la base.

Posté : 21 sept. 2006, 02:06
par graphistnet
Peux tu nous donner la structure exacte de ta table film avec deux ou trois lignes d'exemples?

Posté : 21 sept. 2006, 19:02
par Invité
Voici la requête de création de la table :

# Structure de la table 'film'

CREATE TABLE film (
id int(10) unsigned NOT NULL auto_increment,
date date DEFAULT '0000-00-00' NOT NULL,
titre varchar(255),
cd varchar(20) DEFAULT '0',
resume text,
realisateur varchar(255),
acteur text,
nationalite varchar(255),
annee varchar(10),
duree varchar(20) DEFAULT '0',
genre varchar(50),
type varchar(50),
note varchar(10) DEFAULT 'nn',
PRIMARY KEY (id)
);

Pour les exemples ma table étant pleine, ça va faire bcp bcp de ligne à c/c. Je pense qu'avec la structure il est possible de comprendre mon problème pour quelqu'un qui masterise bien ce sujet. Pour le champ acteur, je peux rentrer donc plusieurs noms, seul bémol, lorsque je veux faire une recherche dans les acteurs avec la requête sql précédemment annoncée pour rechercher les films dans lesquels un acteur à jouer, je me retrouve dans ma liste de choix (balise select) avec tous les acteurs présents dans tous les films, avec donc les doublons et qui plus est sans aucun ordonnancement (classement alphabétique par ex). Toutefois, la requête finale est bonne, puisque j'ai le résultat demandé à savoir tous les films dans lesquels jouent un acteur.

Par exemple, pour 3 films X, Y & Z, je retrouve dans ma balise : tous les acteurs de X, suivis de tous les acteurs de Y et enfin ceux de Z. Si Bruce Willis joue dans les 3 films, je me retrouve donc avec 3 fois Bruce Willis.

J'espère que j'ai été assez clair :) Merci d'avance pour l'aide.

Posté : 21 sept. 2006, 19:14
par iclo
Ce n'est pas une solution directe à ton problème, mais un conseil général: tu aurais vraiment beaucoup à gagner à retravailer ta structure de base de donnée.
Avec au moins une table acteur, pour éviter de la redondance dans la table film.
Et si il peut y avoir plusieurs acteurs dans un même film, une troisième table, mettant les acteurs et les films en relation sera nécessaire.
Avec une tel structure de donnée ton problème de distinct ne se posera même plus, vu qu'il n'y aura plus de redondances de donée.

Je ne s'aurais trop te recommander de jeter un coup à un cours de modélisation de base de donnée.
Bonne continuation,

Posté : 21 sept. 2006, 19:40
par Karter
Vu mon niveau, cette solution me semble difficile à mettre en oeuvre toutefois, c'est effectivement une bonne piste de recherche. Merci à toi. Si quelqu'un à d'autres solutions à me proposer, je suis tout ouie.

Posté : 21 sept. 2006, 20:44
par iclo
C'est toi qui vois, mais une base de donnée mal concue au départ, impose souvent par la suite beaucoup de bricolage en php pour parvenir à réaliser ce qu'on veut, et donc même en étant débutant, je pense qu'une bonne base de donnée simplifie beaucoup les choses.

ps: Plusieurs acteurs dans le même film = plusieurs enregistrement dans la table film pour le moment ?? :?

Posté : 23 sept. 2006, 13:38
par Karter
Oui tout à fait, j'ai environ 5 acteurs par film. Et je suis relativement d'accord avec toi sur ta remarque. Donc si je comprends bien au final ma requête est bonne mais ma table est mal conçue et donc je n'arriverai pas même en bricolant à obtenir ce que je souahite. Merci de m'avoir éclairé.

Posté : 23 sept. 2006, 22:00
par iclo
Je vais détailler un peu plus la solution "normalisée" que j'ai proposée plus haut.

Un des principes de base à avoir à l'esprit quand on concoit une base de donnée, c'est d'éviter d'avoir de l'information en double. (redondance) Principalement pour deux raisons:
- Eviter de perdre de l'espace de stockage (ça peut représenter un coût, ou une limite sur un hébergement)
- Problème de cohérence: si on doit modifier l'information, il faut le faire à plusieurs endroit: on peut oublier de faire certaines modifications, ça demande du travail en plus au serveur, bref c'est lourd...

Pour éviter ça, on va décomposer les tables contenant de la redondances en ajoutant une ou des tables.

On va donc avoir une table film et une table acteur. Comme ça chaque donnée sera unique, un enregistrment par acteur et par film (bien-sur dans chaque table on aura un identifiant unique, logiquement un champ autoincrémenté)

Ensuite, il va falloir lié ces deux tables, commençons par analyser le lien entre les deux:
Un film peut avoir été joué par un ou plusieurs acteurs (0 si c'est un dessin animé muet :D)
Un acteur peut jouer dans un, plusieurs ou 0 films. (ça dépend de son talent en gros :D)

Il va donc falloir une troisième table, qu'on pourrait appeler "joue dans"
qui ne contiendra que deux identifiants : l'identifiant du film et l'identifiant de l'acteur.

Si on a 5 acteurs dans un film, on aura 5 enregistrement dans cette table.

Un petit exemple :

Code : Tout sélectionner

Table film: id titre 1 Film A 2 Film B Acteur id Nom 1 Tom Cruise 2 Donald Duck Joue dans idFilm idActeur 1 1 1 2 2 1

Ce qui en français, veut dire que Tom Cruise et Donald Duck, on joué dans le film A, et que seul Tom Cruise a joué dans le film B.

Je sais bien, qu'une telle structure peut paraitre compliqué à mettre en oeuvre pour un débutant en php/mysql, mais il faut résonner à moyen et long terme: Il vaut mieux prendre le temps, de mettre en place une solution correcte, qui permettra de faire à peu près toutes les manipulations possibles (tris, recherche, ajout/ suppressions d'acteurs et de films) dès le début, que de devoir modifier la base de donnée par après, outre le fait de devoir recommencer le boulot, ça pose des problèmes de récupérer les données déja encodées pour passer d'une solution à une autre.

C'est souvent une erreur chez les gens qui débutent de vouloir aller trop vite, et de partir sur de mauvaises bases.


ps: pas très originial mon exemple, suis pas un très grand cinéphile :D :D