Recuperer les amis qui ne sont pas communs à deux utilisateurs.

Fermé
lollal1756783 Messages postés 2 Date d'inscription dimanche 15 octobre 2017 Statut Membre Dernière intervention 16 octobre 2017 - Modifié le 15 oct. 2017 à 22:22
Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 - 17 oct. 2017 à 09:00
Bonjour,

Voila mes tables:

friends:
| id_invitation
| id_exp
| id_des
| active

users:
| id
| prenom
| nom
| email
| password

j'ai deux requetes:

1: la premiere me retourne la liste des amis .
SELECT *
FROM users U
JOIN friends F
ON ( U.id = F.id_exp AND F.id_des = :id )
OR ( U.id = F.id_des AND F.id_exp = :id )
WHERE U.id <> :id
AND F.active = 1

2: la seconde me retourne uniquement les amis communs entre deux utilisateurs.
SELECT u.id,
u.nom, u.prenom, u.avatar
FROM users u
INNER JOIN
(
SELECT id_exp, id_des
FROM friends
WHERE id_exp IN(:id_exp, :id_des)
AND active = 1
UNION
SELECT id_des, id_exp
FROM friends
WHERE id_des IN(:id_exp, :id_des)
AND active = 1
) tmp ON tmp.id_des = u.id
GROUP BY u.id
HAVING COUNT(*) = 2


Je veux une requete qui va joindre les deux requetes(en haut) pour me retourner uniquement les amis qui ne sont pas communs aux deux utilisateurs.
J'ai fait quelque recherches, on m'a parler de DISTINCT mais je ne trouve de solution.

3 réponses

jordane45 Messages postés 38346 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 16 décembre 2024 4 717
16 oct. 2017 à 09:23
Bonjour,

1 - Ta question concerne une requête SQL ... et non du code php !
Je déplace donc ta question dans le bon forum.

2 - Ta seconde requête peut plus simplement s'écrire comme ceci:
SELECT u.id,
  u.nom, u.prenom, u.avatar
FROM users u
INNER JOIN
(
  SELECT id_exp, id_des
  FROM friends
  WHERE (id_exp IN(:id_exp, :id_des) OR id_des IN(:id_exp, :id_des))
    AND active = 1
) tmp ON tmp.id_des = u.id
GROUP BY u.id
HAVING COUNT(*) = 2


3 - Pour ta question ... il suffit de faire du not in

0
lollal1756783 Messages postés 2 Date d'inscription dimanche 15 octobre 2017 Statut Membre Dernière intervention 16 octobre 2017
Modifié le 16 oct. 2017 à 10:34
"il suffit de faire du not in", COMMENT ?
j'avais esssayé cela:


SELECT *
FROM
users U
INNER JOIN friends F
ON ( U.id = F.id_exp AND F.id_des = :id )
OR ( U.id = F.id_des AND F.id_exp = :id )
WHERE
(U.id <> :id_k
AND F.active = 1)
AND NOT IN
(SELECT u.id,
u.nom, u.prenom, u.avatar
FROM users u
INNER JOIN
(
SELECT id_exp, id_des
FROM friends
WHERE id_exp IN(:id_exp, :id_des)
AND active = 1
UNION
SELECT id_des, id_exp
FROM friends
WHERE id_des IN(:id_exp, :id_des)
AND active = 1
) tmp ON tmp.id_des = u.id
GROUP BY u.id
HAVING COUNT(*) = 2)


Mais fonctionne pas au pire ça produit des erreurs et la section de la page concernée ne s'affiche pas.
Merci.
0
Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 1 011
Modifié le 17 oct. 2017 à 09:03
Bonjour,

Je partirais, pour ma part, de cette requête :
SELECT * 
FROM Users u
LEFT OUTER JOIN Friends f1 
    ON u.id IN (f1.id_exp, f1.id_dest) 
    AND :id_exp IN (f1.id_exp, f1.id_dest) 
    AND u.id <> :id_exp 
    AND f1.active = 1
LEFT OUTER JOIN Friends f2 
    ON u.id IN (f2.id_exp, f2.id_dest) 
    AND :id_dest IN (f2.id_exp, f2.id_dest) 
    AND u.id <> :id_dest 
    AND f2.active = 1

Qui, si je n'ai pas écrit de bêtise (pas évident à conceptualiser sans tester), devrait te ramener une ligne pour chaque User, avec les champs Friends remplis deux fois : tout à NULL si pas ami avec :id_exp, puis tout à NULL si pas ami avec :id_dest.
Du coup il ne reste plus qu'à tester f1.(n'importe quoi) et f2.(n'importe quoi) pour savoir si les gens sont amis avec :id_exp et/ou :id_dest :

Ami avec les deux :
WHERE f1.id_invitation IS NOT NULL AND f2.id_invitation IS NOT NULL


Ami avec un seul des deux :
WHERE (f1.id_invitation IS NOT NULL AND f2.id_invitation IS NULL) OR (f1.id_invitation IS NULL AND f2.id_invitation IS NOT NULL)


Ami avec aucun des deux :
WHERE f1.id_invitation IS NULL AND f2.id_invitation IS NULL


etc.

Xavier

PS : un petit écueil à gérer : à la réflexion, cette requête considère une personne comme non amie avec elle-même, donc dest et exp apparaîtront dans les résultats en conséquence. Tu voudras peut-être les exclure des résultats, avec
WHERE u.id NOT IN (:id_dest, :id_exp)
0