2017-07-19 4 views
1

J'utilise PostgreSQL. Tout ce que je lis ici suggère que dans une requête n'utilisant que des jointures complètes sur une seule colonne, l'ordre des tables jointes n'a pas d'importance. Mon intuition dit que cela devrait aussi aller pour plusieurs colonnes, à condition que chaque colonne commune soit listée dans la requête si possible (c'est-à-dire, partout où les deux tables jointes ont la colonne en commun). Mais c'est pas le cas, et j'essaie de comprendre pourquoi.Pourquoi l'ordre FULL JOIN fait-il une différence dans ces requêtes?

Simplifié à trois tables a, b et c.

Columns in table a: id, name_a 
Columns in table b: id, id_x 
Columns in table c: id, id_x 

Cette requête:

SELECT * 
FROM a 
    FULL JOIN b USING(id) 
    FULL JOIN c USING(id, id_x); 

retourne un nombre différent de lignes que celui-ci:

SELECT * 
FROM a 
    FULL JOIN c USING(id) 
    FULL JOIN b USING(id, id_x); 

Ce que je veux/expect est difficile à articuler, mais fondamentalement, un I » d aimer une fusion complète "complète". Je ne veux pas de champs nulles à moins que cela ne soit inévitable.

Par exemple, à chaque fois qu'il y a un ID non-nul, je veux que la colonne de nom correspondant à toujours ait le nom_a et ne soit pas nulle. Au lieu de cela, l'un de ces exemples de requêtes renvoie des résultats semi-redondants, avec une ligne ayant un nom_a mais pas d'ID et une autre ayant un ID mais pas de nom_a, plutôt qu'une seule ligne fusionnée. Lorsque les jointures sont répertoriées dans l'ordre inverse, j'obtiens le résultat souhaité (mais je ne suis pas sûr des autres problèmes pouvant survenir, car les données futures sont inconnues).

+0

Vous vous attendez à ce qu'il puisse y avoir NULL dans les tables d'entrée? Est-ce que certaines de vos attentes dépendent de FULL JOIN sur les superkeys (UNIQUE NOT NULL)? Existe-t-il d'autres restrictions/contraintes sur les tables ou les jointures? Quels sont exactement vos résultats souhaités/attendus en termes d'intrants? S'il vous plaît donnez l'exemple d'entrée, requête, et prévu/désiré et la production réelle. PS Je soupçonne qu'aucune chaîne de telles jointures n'est la requête pour le résultat que vous voulez. Je soupçonne que vous avez besoin de certains syndicats, et que OU joue un grand rôle dans vos spécifications. Essayez de décrire et donner des exemples pour ce que vous voulez pour 2 puis 3 tables. – philipxy

+0

[Y at-il une règle empirique pour construire une requête SQL à partir d'une description lisible par l'homme?] (Https://stackoverflow.com/a/33952141/3404097) – philipxy

+0

Vous n'êtes toujours pas clair sur ce que vous voulez dans les commentaires que vous avez écrits sur la réponse de GordonLinoff. Aussi, "S'il y a plusieurs rangées avec ..." suggère, comme je l'ai émis dans mon commentaire sur votre question, que votre situation implique certaines hypothèses * mais vous ne les avez pas données *. Les choses sont plus compliquées que vous ne le pensez. Si vous voulez une réponse à votre question, quelle qu'elle soit, veuillez lire et agir sur [mcve], puis lire et agir sur mon commentaire. À tout le moins, donnez un exemple d'entrée et de résultat attendu. En outre, les commentaires ne sont pas pour des clarifications, s'il vous plaît modifier votre question. Aussi, voir ma réponse. – philipxy

Répondre

1

Vos requêtes sont différentes. Dans la première, vous faites full join à b en utilisant une seule colonne, id.

Dans la seconde, vous effectuez un full join à b en utilisant deux colonnes.

Bien que les deux requêtes puissent renvoyer les mêmes résultats dans certaines circonstances, il n'y a pas de raison de penser que les résultats seraient comparables.

+0

Cela a du sens. Mais ce que je ne comprends pas entièrement, c'est comment je peux forcer le 'id 'de la dernière table à toujours être fusionné avec le premier, autant qu'avec le second. Intuitivement c'est comme ça que j'attends que 'FULL JOIN' fonctionne quand j'ai le mot clé' USING', car une seule colonne 'id' est retournée. – Lenoxus

+1

@Lenoxus Que signifie "toujours être fusionné"? PS Définitions, pas d'intuitions. – philipxy

+0

Je comprends pourquoi ce n'est pas clair. Je veux que la table des résultats ait le moins de lignes possible. Donc: pas de valeurs nulles sauf si une valeur serait vraiment indéterminable. S'il existe plusieurs lignes avec, disons, les mêmes valeurs id et id_x, cela doit être dû au fait que les deux tables b et c ont des lignes avec ces valeurs. La table de résultat doit refléter chaque relation/chevauchement dans les données de ces tables, mais pas plus que cela. – Lenoxus

0

L'ordre des arguments est important dans les JOINTS EXTERNES, sauf que FULL NATURAL JOIN est symétrique. Ils renvoient ce qu'une INNER JOIN (ON, USING ou NATURAL) fait mais aussi les lignes sans correspondance des tables gauche (LEFT JOIN), droite (RIGHT JOIN) ou les deux (FULL JOIN) étendues par NULL. L'option USING renvoie la seule valeur partagée pour chaque colonne spécifiée dans les lignes INNER JOIN; dans les lignes étendues NULL, une autre colonne commune peut avoir NULL dans la version d'une table et une valeur dans l'autre.

L'ordre des jointures est également important. Même FULL NATURAL JOIN n'est pas associatif, car avec plusieurs tables, chaque paire de tables (l'opérande étant un résultat original ou joint) peut avoir un ensemble unique de colonnes communes, c'est-à-dire en général (A ⟗ B) ⟗ C ≠ A ⟗ (B ⟗ C).

Il existe de nombreux cas particuliers où certaines identités supplémentaires sont conservées. Par exemple, FULL JOIN à l'aide de tous les noms de colonnes courants et de l'égalité des noms de colonnes OUTER JOIN ON sont symétriques. Certains cas impliquent des CK (clés candidates), des FK (clés étrangères) et d'autres contraintes sur les arguments.

Votre question n'indique pas exactement quelles conditions d'entrée vous assumez ou quelles conditions de sortie vous recherchez.