2009-11-16 3 views
0

Voici les tableaux:Inscrivez-vous pour donner la liste avec une colonne de relation en option

  sets: id INT 

     users: id INT 

     items: id INT 
       setid INT [an item only belongs to one set] 

relationships: userid INT 
       itemid INT 
       relationship WHATEVER 

Maintenant, je suis en train d'écrire une requête SQL pour faire ce qui suit, sans beaucoup de succès.

donné une particulière setid et userid, nous avons besoin de générer une liste de tous les éléments de l'ensemble, avec une colonne contenant la relation utilisateur donné à chaque élément, si une telle relation existe. à-dire idéalement, des colonnes dans les résultats seraient:

setid 
itemid 
relationship 

Mon meilleur effort est avec deux jointure interne énoncés comme suit:

select 
    sets.id as setid, 
    items.id as itemid, 
    relatonships.relationship as relationship 

from sets 
    inner join items on sets.id = items.setid 
    inner join relationships on relationships.itemid = items.id 

where 
    sets.id = [say, 5] 
    and relationships.userid = [say, 27] 

Cependant, il est évident que cela ne fonctionne pas, parce que la deuxième clause where élimine les lignes où il n'existe aucune relation existante entre cet élément et l'utilisateur donné. Je peux voir que vous pouvez effectuer deux requêtes, mais cela semble ... mauvais pour un problème apparemment fondamental.

Je suis sûr que c'est un problème simple et je m'excuse d'être un tel newb SQL!

Modifier

Exemple: Deux articles, 5 et 6, sont en jeu 1. Le courant est userid 15. 15 a une relation existante définie au point 5, mais pas au point 6.

Dans ce cas, l'exécution de la requête ci-dessus dans mysql ne renverra qu'une seule ligne: setid: 1, itemid: 5, relationship: X.

La raison de ceci est que la deuxième clause where élimine la ligne contenant l'élément 6, car pour cet ensemble de résultats provenant des diverses tables, relationships.userid = 15 renvoie la valeur false.

Cela se produit indépendamment de l'utilisation d'une jointure interne ou d'une jointure à gauche.

Répondre

0

pas à 100% ce que vous demandez, par essayer ce

select 
    sets.id as setid, 
    items.id as itemid, 
    relatonships.relationship as relationship 

from sets 
    inner join items on sets.id = items.event 
    LEFT join relationships on relationships.itemid = items.id 

where 
    sets.id = [say, 5] 
    and relationships.userid = [say, 27] 

Gardez à l'esprit que la colonne de relation sera NULL si aucune existe. En outre, la référence de relation dans la clause WHERE peut également supprimer des lignes. J'espère que cela vous permettra de commencer, encore une fois je pourrais mal comprendre ce que vous essayez d'atteindre. De votre conception de table, il ne semble pas y avoir une relation entre l'utilisateur et les ensembles, pourriez-vous éventuellement la liste des champs dans les tables.

Essayez la requête suivante:

select sets.id as setId, 
     items.id as ItemId, 
     relationships.relationship 
from sets 
    join users on 1=1 
    join items on sets.id=items.setid 
    left join relationships on relationships.itemId = items.id 
where 
    sets.id=5 and users.id = 27 

En ajoutant à la jointure avec 1 = 1 la table des utilisateurs, vous n'avez pas besoin de la clause where de référence à la table de relation du tout

Modifier la gauche à rejoindre:

left join relationships on relationships.itemId = items.id 
AND relationships.userId=users.id 
+0

Merci Sparky. Je pense que vous avez très bien compris le problème. Malheureusement, la jointure gauche souffre du même problème: la seconde clause "where" élimine les lignes, et donc les éléments, où aucune relation avec l'utilisateur actuel n'existe actuellement dans la table "relations". J'ai besoin de * tous * les éléments de l'ensemble. Pour certains de ces éléments, il y aura une relation définie avec l'utilisateur donné; pour d'autres, il n'y en aura pas. –

+0

J'ai ajouté un exemple à la question. Je ne sais pas comment l'expliquer mieux. Faites-moi savoir si vous avez des idées! Salut, B –

+0

Désolé Sparky, deuxième réponse est v intelligent, mais pas la solution. Il inclura tous les articles pour lesquels il y a une entrée dans les "relations" sous cet itemid, que cette relation soit ou non liée à l'utilisateur déclaré. Par exemple, si nous avons une relation entre l'utilisateur 3875 et l'article 5, cette relation apparaîtra pour * tout utilisateur *. –

1

Trouvé la solution: pas de seconde où clause, et pas de fudging (astucieux!) Avec join users on 1=1 est nécessaire.

select * from sets 
    inner join items on items.setid = sets.id 
    left join relationships 
     on relationships.itemid = items.id 
     and relationships.userid = [say, 5] 
where 
    sets.id = [say, 1] 

En d'autres termes, la solution a consisté à déplacer la sélection de l'utilisateur dans le tableau relationships d'une clause where à un prédicat supplémentaire dans la deuxième jointure.

+0

Bon sang, vous avez pris ma réponse, sauf que j'ai supprimé avec joindre sur la table 'set'. – outis