2017-09-25 3 views
0

Ceci est la requête:Mysql SELECT que des valeurs uniques dans une colonne lorsque joint à gauche avec une autre table

SELECT a.id, a.userName,if(o.userId=1,'C',if(i.userId=1,'I','N')) AS relation 
     FROM tbl_users AS a 
     LEFT JOIN tbl_contacts AS o ON a.id = o.contactId 
     LEFT JOIN tbl_invites AS i ON a.id = i.invitedId 
    ORDER BY relation 

Cela renvoie la sortie comme suit:

+----+--------------+-------------+ 
| ID | USERNAME  | RELATION | 
+----+--------------+-------------+ 
| 1 |   ray |   C | 
+----+--------------+-------------+ 
| 2 |   john |   I | 
+----+--------------+-------------+ 
| 1 |   ray |   N | 
+----+--------------+-------------+ 

Je dois enlever la troisième ligne à partir de la requête select en vérifiant si possible que l'identifiant est en double. La priorité est la suivante:

C -> I -> N. Donc, car il existe déjà un « rayon » avec un C, je ne veux pas à nouveau avec un I ou N.

J'ai essayé d'ajouter distincts (a.id) mais ça ne marche pas. Comment puis-je faire cela?

Pourquoi DISTINCT ne fonctionne-t-il pas pour cela?

+0

Que voulez-vous faire avec la relation? Il y a deux relations différentes pour '1 rayon C/N' C et N. Êtes-vous sûr de vouloir jeter cette 3ème rangée? –

+0

oui je suis sûr. La priorité est la suivante C -> I -> N. Donc, s'il y a un C avec un userID alors je ne veux pas un N avec ce même ID utilisateur –

+0

Pouvez-vous m'aider mane? Tout avis sera le bienvenu. –

Répondre

1

A partir des spécifications que vous avez donné, tout ce que vous avez à faire est un groupe par ID et le nom d'utilisateur, puis choisissez la valeur la plus faible de la relation que vous pouvez trouver (depuis C < I < N)

SELECT a.id, a.userName, MIN(if(o.userId=1,'C',if(i.userId=1,'I','N'))) AS relation 
    FROM tbl_users AS a 
    LEFT JOIN tbl_contacts AS o ON a.id = o.contactId 
    LEFT JOIN tbl_invites AS i ON a.id = i.invitedId 
GROUP BY a.id, a.username 
+0

Thanks man. Cela a fonctionné pour moi. –

1

Il y a plusieurs façons d'obtenir le maximum/minimum du groupe comme vous pouvez le voir dans ce manual page.

Le meilleur qui vous convient est le premier, si l'ordre des lignes ne peut pas être défini par ordre alphabétique.

Dans ce cas, si l'ordre souhaité était z-a-m (voir le commentaire de Rams), vous auriez besoin de la fonction FIELD().

Votre réponse est

SELECT 
a.id, 
a.userName, 
if(o.userId=1,'C',if(i.userId=1,'I','N')) AS relation 
FROM tbl_users a 
LEFT JOIN tbl_contacts AS o ON a.id = o.contactId 
LEFT JOIN tbl_invites AS i ON a.id = i.invitedId 
WHERE 
if(o.userId=1,'C',if(i.userId=1,'I','N')) = (
    SELECT 
    if(o.userId=1,'C',if(i.userId=1,'I','N')) AS relation 
    FROM tbl_users aa 
    LEFT JOIN tbl_contacts AS o ON aa.id = o.contactId 
    LEFT JOIN tbl_invites AS i ON aa.id = i.invitedId 
    WHERE aa.id = a.id AND aa.userName = a.userName 
    ORDER BY FIELD(relation, 'N', 'I', 'C') DESC 
    LIMIT 1 
) 

Notez que vous pouvez aussi le faire comme ORDER BY FIELD(relation, 'C', 'I', 'N') d'avoir plus lisible/intuitive. Je l'ai inversé, car si vous aviez la possibilité d'avoir un 'X' dans la relation, la fonction FIELD() aurait retourné 0 car X n'est pas spécifié comme paramètre. Par conséquent, il serait trié avant «C». En triant en descendant et en tournant l'ordre des paramètres, cela ne peut pas arriver.

+0

Cette requête ne prendra-t-elle pas beaucoup de temps? Il a "4 jointures à gauche" !! –

+0

Ce n'est pas nécessairement mauvais. Cela dépend si vous avez créé vos tables avec des index appropriés. Si vous avez cette requête ne fera aucun problème. – fancyPants