web-dev-qa-db-fra.com

Joindre des tables sur des colonnes de clé étrangère / primaire composite dans une requête

CREATE TABLE subscription (
   magazine_id bigint,
   user_id     bigint,
   PRIMARY KEY (magazine_id, user_id)
);

CREATE TABLE delivery (
   magazine_id bigint,
   user_id     bigint,
   FOREIGN KEY (subscription) REFERENCES subscription (magazine_id, user_id)
);

Quelle est la bonne façon de rechercher des livraisons avec un abonnement particulier? Existe-t-il un moyen d'attribuer un nom de colonne à PRIMARY KEY (magazine_id, user_id) et la clé étrangère correspondante afin que je puisse interroger comme ceci:

SELECT *
FROM subscription
JOIN delivery ON (delivery.subscription_fk = delivery.subscription_pk);

Remarque: je peux écrire quelque chose comme ceci:

SELECT *
FROM subscription
JOIN delivery ON (delivery.magazine_id = subscription.magazine_id
              AND delivery.user_id = subscription.user_id);

Cependant, j'ai l'impression qu'il existe un moyen moins verbeux d'y parvenir.

21
samol

Il y a un NATURAL JOIN:

SELECT *
FROM   subscription
NATURAL JOIN delivery;

Citer le manuel sur SELECT :

NATURAL

NATURAL est un raccourci pour une liste USING qui mentionne toutes les colonnes des deux tables qui portent les mêmes noms.

Cela fonctionnerait pour votre configuration de test, mais il ne fait pas strictement ce que vous demandez . La connexion est basée sur toutes les colonnes partageant le même nom. Les clés étrangères ne sont pas prises en compte. Les cas où NATURAL JOIN est une bonne idée sont rares.

Simplifiez le code/moins verbeux

Pour commencer, vous pouvez utiliser des alias de table et vous n'avez pas besoin de parenthèses autour des conditions de jointure avec ON (contrairement à USING):

SELECT *
FROM   subscription s
JOIN   delivery     d ON d.magazine_id = s.magazine_id
                     AND d.user_id = s.user_id;

Comme les noms de colonne dans les conditions de jointure sont identiques, vous pouvez simplifier davantage avec USING:

SELECT *
FROM   subscription s
JOIN   delivery     d USING (magazine_id, user_id);

Il n'y a pas de variante de syntaxe faisant automatiquement des jointures basées sur des contraintes de clé étrangère. Vous devrez interroger les catalogues système et créer le SQL dynamiquement.

29
Erwin Brandstetter

delivery n'a-t-il pas deux colonnes représentant la clé étrangère? Ensuite, cela devrait fonctionner comme avec une clé primaire non composite SELECT * FROM subscription JOIN delivery ON (delivery.magazine_id = subscription.magazine_id AND delivery.user_id = subscription.user_id).

1
Smutje