web-dev-qa-db-fra.com

Puis-je sauter la table intermédiaire dans une jointure?

J'ai écrit cette requête:

SELECT 
    "BD - Utilizadores".Utilizador, 
    "BD - Utilizadores"."Palavra passe", 
    "BD - Áreas".área 
FROM "BD - Utilizadores" 
INNER JOIN "BD - Permissões" 
    on "BD - Utilizadores".id = "BD - Permissões"."user_id" 
Join "BD - Áreas" 
    on "BD - Permissões".area_id = "BD - Áreas".id

Je veux rejoindre les données de la table "BD - UTILIZADORES" avec "BD - ÁREAS". Puisqu'ils n'ont pas de lien direct, je devais utiliser un "homme au milieu" I.e. "BD - permissões". Voici le diagramme:

Link Tables

Ma question principale est: y a-t-il une autre façon de le faire et d'obtenir le même résultat?

6
Eudes

tl; dr

La réponse courte est non. Vous devez faire la jointure multiple, même si vous ne voulez que des colonnes des deux tables 'de chaque côté ".

Conception de table

Cela semble être une douleur, mais bien que cela rend vos questions plus longues, il est beaucoup plus important d'obtenir la structure de la base de données, y compris les clés étrangères correctement, qu'il s'agit de faire des requêtes courtes.

Il y a quelques façons d'organiser des clés étrangères, parfois avec des tables supplémentaires qui ne sont là que là pour exprimer des relations. Par exemple, si chaque chat a une souris unique, il pourrait y avoir une clé étrangère de chat à la souris avec une contrainte unique. Cela pourrait même être la clé principale du chat. Si chaque chat a zéro ou plus de souris, mais pas de souris ayant plus d'un chat, vous auriez une clé étrangère habituelle de la souris au chat. Si chaque chat a zéro ou plus de souris, et chaque souris a zéro ou plus de chats, vous créeriez une troisième table CaMousematching, qui a une entrée pour chaque "bord" entre un chat et une souris, avec des clés étrangères sur le chat et la Souris. Vous apprendrez que ces modèles sont très importants et les cas de base couvrent beaucoup de situations.

Maintenant, supposons que vous inverseriez les clés étrangères de votre conception de table, de sorte que Utilizadors et Areas _ Les deux ont une clé étrangère pour Permissoes. Cela signifierait que vous pouvez simplifier la jointure - parce que vous pourriez filtrer sur permissoe_id étant égal dans les deux tables. Cependant, ce serait une relation assez étrange entre Utilizador et Area qui pourrait ne pas correspondre à la réalité. Vous pourriez avoir un Utilizador associé à un Permissoe qui n'avait aucun Area lié à celui-ci. Ceci Utilizador disparaîtrait simplement de la jointure interne.

Cela pourrait seulement avoir un sens s'il y avait une entité réelle qui a formé le lien entre les deux entités. Par exemple, chaque chat vit dans une maison et chaque souris habite dans une maison. Vous pouvez facilement trouver les paires de souris chat qui vivent dans la même maison.

Conseils pratiques

Vous pouvez toujours créer une vue, ce qui fait une requête commune comme une table. Votre requête ci-dessus pourrait être définie comme la vue, puis d'autres requêtes pourraient en choisir et y participer, sans avoir à comprendre ce que les jointures constituent la vue en interne.

Si vous ne créez pas de vue, vous pouvez au moins sauvegarder l'extrait de code qui fait la jointure, afin que vous puissiez la coller dans d'autres requêtes similaires plus tard.

9
jwg

Si tel est le résultat souhaité (toutes les combinaisons d'autorisations définies entre les utilisateurs de la région), alors non.

Si vous souhaitez répertorier toutes les zones et les utilisateurs avec leurs autorisations respectives, notamment si aucune autorisation n'est définie, vous devez alors que vous ayez besoin de CROSS JOIN ces table alors LEFT OUTER JOIN Le tableau des autorisations aux deux.

À titre de note latérale: il peut être au-delà de votre contrôle s'il s'agit de la DB de quelqu'un d'autre, mais j'éviterais des espaces dans des noms de table dans la mesure du possible et des caractères non-ANSI. Cela facilitera le code (bien que cela soit bien sûr d'une opinion subjective), évitez de la nécessité d'échapper aux noms avec des citations ou des supports et de réduire les problèmes plus tard si vous devez accéder à la DB avec des outils qui ne supportent pas de telles choses. Dans les noms ou besoin de migrer la base de données vers une autre plate-forme qui ne le fait pas.

6
David Spillett

Je pense que vous pouvez mélanger la syntaxe et la sémantique. Il est syntaxiquement correct de rejoindre deux tables sur toutes les colonnes de type compatibles. Par exemple, vous pouvez rejoindre Utilizadores et Áreas sur email = area. Ce serait légal SQL de le faire, mais cela n'aurait pas de sens. En d'autres termes, syntaxiquement valide mais sémantiquement invalide.

La table permissões est là pour une raison. Son existence enregistre le sens. Une ligne de cette table relie un utilisateur à une zone pour une raison. Il se peut que l'utilisateur gère cette zone ou se vend dans cette zone ou est interdite d'entrer dans cette zone ou de toute autre possibilité. La situation réelle mondiale que vos modèles de base de données détermineront quelle est la signification. Il peut y avoir plusieurs raisons de rejoindre deux choses et ces raisons devraient être modélisées séparément. Prenez l'exemple d'une personne et d'une voiture. La même personne peut être le propriétaire enregistré de la voiture, il aurait peut-être payé pour cela et il peut le conduire en ce moment. Ce sont trois faits différents, cependant, aucun implique l'autre, chacun a une sémantique différente et doit être modélisé séparément.

En rejoignant Permissões, vous utilisez la sémantique intégrée à cette table. Toute autre jointure aura une sémantique différente, donc même s'il renvoie la même chose valeurs Il aura différent sens et ne sera donc pas équivalent.

5
Michael Green