Comparer résultat d'une requete

Eléphant du PHP | 282 Messages

12 juin 2019, 22:20

Bonjour,

J'essaie en vain de faire une requête qui serait capable de comparer des champs entre eux mais je dois dire que je bloque vraiment.
Le principe de ma requête serait de faire un système d'affinité des membres de mon site en fonction de leur notation de film. Donc si un membre a noté uniquement un film et qu'il va sur le profil d'un autre membre qui a déjà voté ce film lui aussi, je voudrais que cela lui affiche une affinité de 100%.

Malheureusement je bloque sur la requête.

J'ai commencé comme ça :
  $getAffinityUserQuery = $bdd->prepare("
    SELECT
      n.id,
      n.user_id
    FROM `notes_films` n
    WHERE

  ");
  $getAffinityUserQuery->bindValue(':user_id', $_GET['id'], PDO::PARAM_INT);
  $getAffinityUserQuery->bindValue(':user_session', $_SESSION['id'], PDO::PARAM_INT);
  $getAffinityUserQuery->execute();

Je ne sais vraiment pas par ou commencer. Il faudrait comparé les notes du membre dont la session est en cours à celui dont le membre affiche le profil.
Je sais qu'en deux requêtes c'est possible, mais j'aurais aimé faire ça en une seule pour que ça fasse plus propre.

Merci à ceux qui pourront m'aider ! :)

Modérateur PHPfrance
Modérateur PHPfrance | 2573 Messages

14 juin 2019, 23:25

Bonjour.
Supposons que je suis l'utilisateur en cours de session et qu'on a les variables suivantes :
  • $id_membre : l'id du membre dont je consulte le profil
    $id_film : l'id du film sujet de notation que j'ai noté moi même
Pour vérifier si le membre ($id_membre) a une affinité de 100% avec moi, il faut qu'il figure dans la table `notes_films` pour le film ($id_film) en question comme j'y figure moi-même.

Donc, voici la requête :
 SELECT count(*) as NB  FROM `notes_films`  WHERE  id = :id_film AND user_id = :id_membre
Qui retourne un nombre NB si > à 0 signifie que le membre en question a noté aussi mon film et donc il a une affinité avec moi.

A+
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 282 Messages

Hier, 16:29

Salut Sadeq,

Merci de ton aide !
Je comprends bien ta requête mais je ne vois pas comment elle peut savoir qui est l'utilisateur dont la session est active ?
Et comment faire si l'utilisateur a noté plusieurs films en commun avec le membre dont il visite le profil.

Avatar du membre
Mammouth du PHP | 866 Messages

Hier, 21:28

Salut, tu dois normalement savoir quel est l'id du film, quel est l'id de l'utilisateur connecté et quel est l'id de la fiche membre.

Après tu fais 2 requêtes, une pour l'utilisateur et une pour le membre de la fiche.
SELECT * FROM note_films WHERE id_film = :id_film AND user_id = :user_id
avec :user_id égal à l'id de l'utilisateur puis à l'id de la fiche membre. Si chacune des requêtes te retourne 1 ligne alors il y a match.

A mon sens tu devrais aussi comparer les notes et intégrer ça à ton calcul d'affinité mais bon peut être dans un deuxième temps quand tu arriveras déjà à gérer la première partie.

Et si tu veux comparer pour tous les films, ben tu fais un peu pareil. Tu récupères d'abord tous les id de films notés par l'utilisateur.
SELECT id_film FROM notes_film WHERE user_id = :user_id
tu peux en extraire un tableau avec tous les id de films et faire un simple count pour connaitre leur nombre.
Puis tu peux faire un
SELECT count(id) AS number FROM `notes_films` WHERE  id_film IN (:film_ids) AND user_id = :id_membre
et comparer les deux nombres.

Faut savoir rester simple des fois. Tu peux peut être faire le tout en une seule requête bien chiadée quand t'es un as du SQL mais tu peux aussi le faire avec quelques requêtes simples sans te prendre la tête. ;)

Après dans les faits c'est pas aussi simple. Ton premier utilisateur a peut être noté 10 films alors que le second en a noté 20. En admettant que le second utilisateur dans ses 20 films notés a noté les 10 films du premier utilisateur, le premier utilisateur aura une affinité de 100% alors que le deuxième aura une affinité de 50%. A moins que tu ignores les 10 films que le premier utilisateur n'a pas notés mais dans ce cas il suffirait d'avoir 1 seul film en commun pour avoir une affinité de 100%... ce qui me semble un peu léger.
Si tu veux que chacun voit le même score d'affinité l'un vis à vis de l'autre avec un calcul d'affinité concret, tu dois te baser sur les films notés en commun ET sur les notes données.

Par exemple en admettant que la notation aille de 1 à 5, tu pourrais considérer que la même note donne une affinité de 100% pour le film, que un 0 face à un 5 donne une affinité de 0%. Dans la logique un écart de note de 1 point vaut 20% d'affinité en moins (un 4 face à un 5 donne 80%, un 2 face à un 4 donne 60%, etc). Tu détermines donc pour chaque film en commun le score d'affinité puis tu fais une moyenne des affinités, total des affinités / nombre de films notés en commun. 8-)

Je te laisse un algo en pseudo code avec quelques fonctions php utiles pour te simplifier la tâche. Le calcul de l'affinité par film est à vérifier mais je crois qu'il est bon.
// récupérer ids films utilisateur
// récupérer ids films membre
// tableau ids films communs = array_intersect(tableau ids films utilisateur, tableau ids films membre)

// initialiser tableau affinités
// boucle sur tableau ids films communs
  // récupérer note utilisateur
  // récupérer note membre
  // calcul affinité film : 100 - abs(note utilisateur - note membre) * (100 / note max possible)
  // ajouter affinité film dans tableau affinités
// fin boucle

// calcul affinité membres : array_sum(tableau affinités) / count(tableau affinités) ♥
J'édite souvent mon message après avoir répondu pour le corriger où y apporter des informations complémentaires alors n'hésitez pas à y jeter un nouveau coup d'oeil ^^