2013-08-15 6 views
4

J'ai un problème où je dois essayer de trouver des personnes qui ont d'anciens comptes avec un solde impayé, mais qui ont créé un nouveau compte. Je dois les comparer en comparant les SSN. Le problème est que nous avons des contacts principaux et supplémentaires, donc 2 SSN potentiels par compte. Je dois le faire correspondre même si elles étaient primaires au début, mais maintenant sont secondaires etc.Requête SQL avec plusieurs jointures possibles (ou condition dans jointure)

C'était ma première tentative, je compte juste maintenant pour obtenir les jointures et les conditions. Je sélectionnerai les données réelles plus tard. Fondamentalement, la table personnelle est jointe une fois aux comptes actifs, et une autre copie aux comptes en souffrance. Les deux références à la table personnelle sont ensuite comparées en fonction des 4 façons possibles d'associer les SSN.

select count(*) 
from personal pa 
join consumer c 
on c.cust_nbr = pa.cust_nbr 
and c.per_acct = pa.acct 
join personal pu 
on pu.ssn = pa.ssn 
or pu.ssn = pa.addl_ssn 
or pu.addl_ssn = pa.ssn 
or pu.addl_ssn = pa.addl_ssn 
join uncol_acct u 
on u.cust_nbr = pu.cust_nbr 
and u.per_acct = pu.acct 
where u.curr_bal > 0 

Cela fonctionne, mais cela prend 20 minutes pour s'exécuter. J'ai trouvé cette question Is having an 'OR' in an INNER JOIN condition a bad idea? donc j'ai essayé de le réécrire comme 4 requêtes (une par combinaison ssn) et de les unir. Cela a pris 30 minutes à courir.

Existe-t-il une meilleure façon de procéder, ou est-ce simplement un processus vraiment inefficace, peu importe comment vous le faites?

Mise à jour: Après avoir joué avec certaines options ici, et d'autres expériences, je pense que j'ai trouvé le problème. Notre fournisseur de logiciels crypte les SSN dans la base de données et fournit une vue qui les décrypte. Comme je dois travailler à partir de cette vue, il faut vraiment beaucoup de temps pour déchiffrer et comparer.

+3

Comment les tables sont-elles indexées? Vous pourriez obtenir une accélération significative si vous indexez par ssn et addl_ssn (index distincts pour chacun) – SWeko

+0

La base de données est gérée par notre fournisseur de logiciels. Je ne suis pas sûr comment l'indexation est mise en place ou si je pourrais les faire changer cela. Je pourrais vérifier cela. – Mike

Répondre

2

Si vous exécutez des jointures séparées, puis l'union alors, alors vous pourriez avoir des problèmes. Que faire si la même paire d'enregistrements remplit au moins deux conditions? Vous aurez des doublons dans votre résultat alors. Je crois que votre première approche est faisable, mais n'oubliez pas que vous joignez quatre tables. Si le nombre de lignes est A, B, C, D dans les tables respectives, alors le SGBDR devra vérifier un maximum d'enregistrements A * B * C * D. Si vous avez plusieurs enregistrements dans votre base de données, cela prendra beaucoup de temps.

Bien sûr, vous pouvez optimiser votre requête en ajoutant des index à certaines colonnes et ce serait une bonne idée si elles ne sont pas déjà indexées. Mais n'oubliez pas que si vous ajoutez un index à une colonne, le RDBMS sera plus rapide à lire à partir de là, mais plus lent à écrire. Si vos opérations sont principalement des lectures (select), alors vous devriez indexer vos colonnes, mais pas à l'aveuglette, étudiez un peu l'indexation avant de commencer.

En outre, si vous adhérez quatre tables, personnels, consommateurs, personnel (encore une fois) et uncol_acct, alors vous pourriez faire quelque chose comme ceci:

Ecrivez une requête, qui contient deux sous-requêtes, chacun d'eux nommé t1 et t2, respectivement. La première sous-requête rejoint personal et consumer et nommera le résultat comme t1. La deuxième requête rejoindra la deuxième occurrence de personal avec uncol_acct et la clause where sera dans votre seconde jointure. Comme décrit précédemment, votre requête contiendra deux sous-requêtes, nommées respectivement t1 et t2. Votre requête rejoindra t1 et t2. De cette façon, vous opimisez, car votre requête principale ne considérera que l'appariement de t1 et t2 valides.

Aussi, si votre clause where est à l'extérieur comme dans votre exemple de requête, alors la jointure à 4 dimensions sera exécutée et seulement après cela sera pris en considération. C'est pourquoi la clause where doit être dans la deuxième sous-requête, donc la clause where sera exécutée avant la jointure principale. En outre, vous pouvez créer une sous-requête à l'intérieur de la deuxième sous-requête pour calculer l'endroit où la condition est rarement remplie.

À la votre!

+0

L'indexation est gérée par notre fournisseur de logiciel et je ne sais pas si je pourrais les faire changer ou non. C'est une procédure rare et pas sensible au temps, donc cela ne vaut probablement pas la peine. J'aime les 2 idées de sous-requêtes, je verrai si c'est plus rapide. En ce qui concerne les enregistrements en double, je ne pense pas que cela se passe parce que mes comptes sont les mêmes pour les deux méthodes. En outre, ce ne serait pas très important dans ce cas parce que quelqu'un ira sur la liste pour essayer de traquer les gens. S'ils se présentent deux fois, ça va. – Mike

+0

+1 pour la réponse "informative" –

+0

Des enregistrements dupliqués se produiront dans le cas où vous êtes en union si et seulement si il y a au moins une paire où plus d'une des conditions de jointure est remplie. Vous pouvez empêcher cela en utilisant le mot clé distinct. Cependant, la solution proposée dans ma réponse empêche cela car les requêtes ne sont pas partitionnées, seules les jointures sont reformatées en utilisant des sous-requêtes pour accélérer les choses. –

Questions connexes