2013-08-20 4 views
0

J'ai différentes tables/vues que je tire de: Invoice, Detail, contact, party, address et remarks.Joindre deux tables sans colonnes combinant

Fondamentalement, je besoin d'extraire des données de la table remarks et la seule façon de le relier à la table party est d'accéder au reste de la table remarks pour faire référence à sa colonne id qui est une clé étrangère sur la table party.

Le id est également une colonne dans la vue Invoice donc quand la clause FROM exécute combine que les champs d'identification sur le côté Invoice et il n'y a rien à rapporter aux autres remarks colonnes. ne peuvent pas être modifiés également les noms sur les colonnes de deux tables:

SELECT * 
FROM Invoice as invoice_view LEFT OUTER JOIN 
    Detail as details ON invoice_view.transact = details.transact LEFT OUTER JOIN 
    contact AS co_contact ON invoice_view.company = co_contact.party LEFT OUTER JOIN 
    contact AS cp_contact ON invoice_view.company = cp_contact.party INNER JOIN 
    party as main_party ON invoice_view.party = main_party.party INNER JOIN 
    party as pay_party ON invoice_view.pay = pay_party.party INNER JOIN 
    party as rec_party ON invoice_view.rec = rec_party.party LEFT OUTER JOIN 

    contact as rec_contact ON rec_party.party = rec_contact.party INNER JOIN 
    address as rec_address ON rec_contact.party = rec_address.party AND rec_contact.address = rec_address.addresscode LEFT OUTER JOIN 
    contact AS pay_contact ON pay_party.party = pay_contact.party INNER JOIN 
    adddress AS pay_address ON pay_contact.party = pay_address.party AND pay_contact.address = pay_address.addresscode AND pay_party.party = pay_address.party LEFT OUTER JOIN 
--What I tried to get it working 
    remark as cp_remark CROSS JOIN 
party as custom_party 

WHERE 
    ( (custom_party.party = pay_party.party) AND (custom_party.id = cp_remark.id)    OR (cp_remark.id IS NULL) OR (custom_party.remark = 0)) 
--More where statements that have no affect on this 
+0

Tout fonctionne-t-il comme prévu? – JsonStatham

+0

Quelle est la question? –

+1

Si vous modifiez select * pour ne sélectionner que les champs dont vous avez besoin, le problème des noms de champs ambigus devrait disparaître. –

Répondre

3

Vous devez ajouter une condition ON à votre remark rejoindre et de se débarrasser de cette CROSS JOIN. Par exemple, vous pouvez faire:

LEFT OUTER JOIN remark as cp_remark ON cp_remark.id = main_party.id OR cp_remark.id = pey_party.id OR cp_remark.id = rec_party.id  

Sur une note de côté, quelques recommandations:

  • Ne pas utiliser la SELECT * sauf si vous écrivez une requête pour votre propre consommation. Votre code devrait vous montrer quelles données vous utilisez, incluez-le seulement dans le jeu de résultats.
  • C'est une préférence personnelle, mais j'ai toujours trouvé que mettre vos jointures sur la gauche est beaucoup plus facile que de les placer sur la droite.
  • Commandez votre JOIN d'une manière plus logique, votre deuxième JOIN nécessite des données de votre septième, essayez d'ajouter des détails au fur et à mesure.
  • Vous rejoignez bien trop de tables, vous n'avez pas besoin de joindre tout ce qui a une clé étrangère, seulement les données que vous tirez pour cette requête exacte. Votre jointure finale est une jointure complète (pas de ON) et est suivie d'un CROSS JOIN (ils sont équivalents), aucun de ces deux n'est une bonne idée dans la plupart des cas. Dans les deux cas, les résultats complets de la table sont ajoutés à l'ensemble de résultats.
  • Les clés étrangères sont utilisées à titre indicatif et, pour l'intégrité des données, elles ne définissent pas le fonctionnement réel des jointures.
  • Les colonnes nommées de la même manière peuvent être résolues en utilisant table.column que vous utilisez déjà pour vos jointures.

Voici comment je formaterais votre version originale.(Comme je ne sais pas quels sont les changements exacte serait le mieux pour votre ensemble de données, je ne comprend pas ma recommandation pour cette ici)

SELECT * 
FROM Invoice as invoice_view 
LEFT OUTER JOIN Detail as details ON invoice_view.transact = details.transact 
INNER JOIN party as main_party ON invoice_view.party = main_party.party 
LEFT OUTER JOIN contact AS co_contact ON invoice_view.company = co_contact.party 
LEFT OUTER JOIN contact AS cp_contact ON invoice_view.company = cp_contact.party 

INNER JOIN party as rec_party ON invoice_view.rec = rec_party.party 
LEFT OUTER JOIN contact as rec_contact ON rec_party.party = rec_contact.party 
INNER JOIN address as rec_address ON rec_contact.party = rec_address.party 
           AND rec_contact.address = rec_address.addresscode 

INNER JOIN party as pay_party ON invoice_view.pay = pay_party.party 
LEFT OUTER JOIN contact AS pay_contact ON pay_party.party = pay_contact.party 
INNER JOIN adddress AS pay_address ON pay_contact.party = pay_address.party 
            AND pay_contact.address = pay_address.addresscode 
            AND pay_party.party = pay_address.party 
--What I tried to get it working        
LEFT OUTER JOIN remark as cp_remark 
CROSS JOIN party as custom_party 
WHERE 
((custom_party.party = pay_party.party) 
    AND (custom_party.id = cp_remark.id) 
    OR (cp_remark.id IS NULL) 
    OR (custom_party.remark = 0)) 
--More where statements that have no affect on this 

EDIT:

Depuis que vous avez demandé à ce que les jointures faire:

  • Rejoignez/jointure interne - ne prendre que les lignes qui ont des données dans les deux tables
  • gauche Adhérez/jointure externe gauche - ne prendre que les lignes qui ont des données dans la table gauche (celle qui ne figurent pas), prendre des données de le droit si disponible
  • droit rejoindre/jointure externe gauche - en face de jointure gauche (rarement utilisé depuis joindre à gauche est plus fréquemment utilisé)
  • jointure externe - données soit rangée crée des données dans la sortie
  • rejoindre sans que/cross joindre - retour toutes les combinaisons de lignes entre les deux tables

Par exemple:

Tableau A: 1,2,3,4
Tableau B: 5,6
Cross rejoindre A, B: (1, 5), (2,5), (3,5), (4,5), (1,6), (2,6), (3,6), (4,6

Notez que les jointures internes commencent en tant que jointures croisées mais sont limitées par la clause ON. C'est fondamentalement une manière de spécifier les conditions de la jointure dans un emplacement plus commode (dans la jointure plutôt que dans le où). Les jointures externes peuvent être conceptuellement considérées comme des jointures internes avec une ligne vide ajoutée aux tables optionnelles (qui correspond si et seulement si aucune autre ligne ne correspond).

+2

Personnellement, je trouve que je fais aussi beaucoup moins d'erreurs si je mets d'abord des jointures internes puis des jointures à gauche puis des jointures croisées. – HLGEM

+2

@HLGEM: C'est vrai, j'ai eu du mal à trouver exactement ce que recherchait la requête, donc regroupé par objectif pour être aussi général que possible. Idéalement, vous commencez avec les termes les plus généraux, puis allez plus en détail (qui suit généralement le modèle que vous mentionnez). – Guvante

+0

qui était plus orienté vers l'OP que vous. – HLGEM