C'est un peu compliqué, mais j'ai 2 tables. Disons que la structure ressemble à ceci:
*Table1*
ID
PhoneNumber1
PhoneNumber2
*Table2*
PhoneNumber
SomeOtherField
Les tables peuvent être jointes sur la base de Table1.PhoneNumber1 -> Table2.PhoneNumber ou Table1.PhoneNumber2 -> Table2.PhoneNumber.
Maintenant, je veux obtenir un jeu de résultats contenant PhoneNumber1, SomeOtherField qui correspond à PhoneNumber1, PhoneNumber2 et SomeOtherField qui correspond à PhoneNumber2.
J'ai pensé à 2 façons de le faire - soit en joignant deux fois sur la table, soit en joignant une fois avec un OR dans la clause ON.
Méthode 1:
SELECT t1.PhoneNumber1, t1.PhoneNumber2,
t2.SomeOtherFieldForPhone1, t3.someOtherFieldForPhone2
FROM Table1 t1
INNER JOIN Table2 t2
ON t2.PhoneNumber = t1.PhoneNumber1
INNER JOIN Table2 t3
ON t3.PhoneNumber = t1.PhoneNumber2
Cela semble fonctionner.
Méthode 2:
Pour en quelque sorte avoir une requête qui ressemble un peu à ceci -
SELECT ...
FROM Table1
INNER JOIN Table2
ON Table1.PhoneNumber1 = Table2.PhoneNumber OR
Table1.PhoneNumber2 = Table2.PhoneNumber
Je n'ai pas encore réussi à faire fonctionner cela et je ne sais pas s'il existe un moyen de le faire.
Quel est le meilleur moyen d'y parvenir? Aucune solution ne semble simple ni intuitive ... Existe-t-il un moyen plus simple de procéder? Comment cette exigence est-elle généralement mise en œuvre?
Premièrement, j'essaierais de refactoriser ces tables pour éviter d'utiliser des numéros de téléphone comme des clés naturelles. Je ne suis pas un fan des clés naturelles et c’est un bon exemple. Les clés naturelles, notamment les numéros de téléphone, peuvent changer fréquemment. Mettre à jour votre base de données lorsque ce changement se produira sera un mal de tête énorme, sujet aux erreurs. *
Méthode 1 comme vous le décrivez, c'est votre meilleur pari cependant. Le schéma de nommage et les alias courts donnent une impression de lacune, mais l'alias est votre ami quand il s'agit de joindre la même table plusieurs fois ou d'utiliser des sous-requêtes, etc.
Je voudrais juste nettoyer un peu les choses:
SELECT t.PhoneNumber1, t.PhoneNumber2,
t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2
FROM Table1 t
JOIN Table2 t1 ON t1.PhoneNumber = t.PhoneNumber1
JOIN Table2 t2 ON t2.PhoneNumber = t.PhoneNumber2
Ce que j'ai fait:
* Pour éviter les problèmes liés à la mise à jour des clés naturelles, les administrateurs de bases de données évitent de spécifier des clés primaires et des contraintes de clé étrangère, ce qui aggrave encore les problèmes liés à une conception médiocre de la base de données. J'ai effectivement vu cela plus souvent qu'autrement.
La première est valable à moins que Phone1 ou (plus probablement) phone2 ne soit nul. Dans ce cas, vous souhaitez utiliser une jointure gauche au lieu d'une jointure interne.
C'est généralement un mauvais signe lorsque vous avez une table avec deux champs de numéro de téléphone. Cela signifie généralement que la conception de votre base de données est défectueuse.
Mon problème était de afficher l'enregistrement même s'il n'existe pas ou un seul numéro de téléphone (carnet d'adresses complet). C’est pourquoi j’ai utilisé un LEFT JOIN qui prend tous les enregistrements de la gauche, même s’il n’existe pas de correspondance à droite. Pour moi, cela fonctionne dans Microsoft Access SQL (ils ont besoin de la parenthèse!)
SELECT t.PhoneNumber1, t.PhoneNumber2, t.PhoneNumber3
t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2, t3.someOtherFieldForPhone3
FROM
(
(
Table1 AS t LEFT JOIN Table2 AS t3 ON t.PhoneNumber3 = t3.PhoneNumber
)
LEFT JOIN Table2 AS t2 ON t.PhoneNumber2 = t2.PhoneNumber
)
LEFT JOIN Table2 AS t1 ON t.PhoneNumber1 = t1.PhoneNumber;
La première méthode est la bonne approche et fera ce dont vous avez besoin. Cependant, avec les jointures internes, vous ne sélectionnerez que les lignes de Table1
si les deux numéros de téléphone existent dans Table2
. Vous voudrez peut-être faire un LEFT JOIN
pour que toutes les lignes de Table1
sont sélectionnés. Si les numéros de téléphone ne correspondent pas, le SomeOtherField
s sera nul. Si vous voulez vous assurer que vous avez au moins un numéro de téléphone correspondant, vous pouvez alors faire WHERE t2.PhoneNumber IS NOT NULL OR t3.PhoneNumber IS NOT NULL
La deuxième méthode pourrait avoir un problème: que se passera-t-il si Table2
a les deux PhoneNumber1
et PhoneNumber2
? Quelle ligne sera sélectionnée? Selon vos données, clés étrangères, etc., cela peut poser problème ou non.
Vous pouvez utiliser UNION
pour combiner deux jointures:
SELECT Table1.PhoneNumber1 as PhoneNumber, Table2.SomeOtherField as OtherField
FROM Table1
JOIN Table2
ON Table1.PhoneNumber1 = Table2.PhoneNumber
UNION
SELECT Table1.PhoneNumber2 as PhoneNumber, Table2.SomeOtherField as OtherField
FROM Table1
JOIN Table2
ON Table1.PhoneNumber2 = Table2.PhoneNumber