2010-01-23 6 views
1

J'ai une requête SQL:Cette requête sql peut-elle être simplifiée?

select * from contactmeta 
WHERE 
contactmeta.contact_id in 
(
select tob.object_id from tagobject tob, tag t, taggroup tg 
where tob.tag_id = t.tag_id 
and t.tag_group_id = tg.tag_group_id 
and tob.object_type_id = 14 
and tg.org_id = contactmeta.group_id 
and (t.name like '%campaign%') 
) 
AND 
contactmeta.contact_id in 
(
select tob.object_id from tagobject tob, tag t, taggroup tg 
where tob.tag_id = t.tag_id 
and t.tag_group_id = tg.tag_group_id 
and tob.object_type_id = 14 
and tg.org_id = contactmeta.group_id 
and (t.name like '%bounced%') 
) 

Mon problème est que je dois simplifier la partie de la requête dans la clause WHERE (je ne peux pas faire une autre se joindre à la table de contactmeta etc.). Cela est dû au fait que la clause WHERE est créée dynamiquement sur un sql autrement statique.

Vous pouvez voir que la condition where est presque la même sauf pour la condition t.name.

Merci pour votre temps

SK

+0

Il existe une autre différence dans vos sous-requêtes. Le premier a t.tag_group_id = tg.tag_group_id, le second ne l'est pas. – rayd09

+0

@ rayd09: Je pense que c'est juste une erreur de copier-coller car la deuxième sous-requête a 'tob.tag_id = t.tag_id' deux fois. @Samuel: est-ce vrai? ou la question dans votre question est-elle correcte? –

+0

Oui, il s'agit d'une erreur couper-coller ... désolé à ce sujet ... laissez-moi voir si je peux le modifier. – Samuel

Répondre

2

ce n'est pas vraiment plus simple (en termes de code), mais sera plus performant, puisque vous utilisez des jointures plutôt que l'opérateur IN:

select contactmeta .* from contactmeta 

inner join tagobject tob, tag t, taggroup tg 
on tob.tag_id = t.tag_id 
and t.tag_group_id = tg.tag_group_id 
and tob.object_type_id = 14 
and tg.org_id = contactmeta.group_id 
and (t.name like '%campaign%') 

inner join tagobject tob2, tag t2, taggroup tg2 
on tob2.tag_id = t2.tag_id 
and t2.tag_group_id = tg2.tag_group_id 
and tob2.object_type_id = 14 
and tg2.org_id = contactmeta.group_id 
and (t2.name like '%bounced%') 

EDIT: si cela est impossible (en raison de vos commentaires sur JOIN limites), alors vous pourriez partie abstraite de la logique en vue par exemple

create view myView 
as 
select * from tagobject tob, tag t, taggroup tg 
    on tob.tag_id = t.tag_id 
    and t.tag_group_id = tg.tag_group_id 

puis d'utiliser cette vue dans votre SQL d'origine.

+0

@davek: OP écrit qu'ils ne peuvent pas modifier la structure de la requête, mais ont besoin d'une solution pour la clause WHERE. –

+0

Un problème possible avec la première solution ici est que, alors que la requête actuelle de OP ne renvoie qu'une seule entrée de contactmeta, ici il peut y avoir plusieurs résultats si les deux jointures internes retournent des nombres d'enregistrements différents. – MartW

+0

ok corrigé la requête maintenant – Samuel

0

Essayez ceci:

select * from contactmeta 
WHERE 
contactmeta.contact_id in 
(
select tob.object_id from tagobject tob, tag t, taggroup tg 
where tob.tag_id = t.tag_id 
and tob.object_type_id = 14 
and tg.org_id = contactmeta.group_id 
and (
    (t.tag_group_id = tg.tag_group_id and t.name like '%campaign%') 
    or 
    (tob.tag_id = t.tag_id and t.name like '%bounced%') 
) 
) 
+1

Je ne pense pas que ce soit pareil, même si au début je pensais la même chose. La requête OP correspond aux lignes qui ont au moins une ligne avec "campaign" ** et ** au moins une ligne avec "bounced". Votre requête correspond déjà aux lignes qui ont ** soit ** "campagne" ** ou ** "rebondi" (ou les deux), mais ** n'exigent pas ** les deux. –

+0

pas tout à fait correct. Sa requête devrait rejoindre le contactmeta avec (tag/tagobject/taggroup) deux fois en raison de la condition AND pour les 2 noms. – rayd09

+0

Ce que dit Bandi-T me semble juste. – rayd09

2

Comme mentionné précédemment, les sous-requêtes dans la clause WHERE ne sont pas les mêmes.

Je ne suis pas sûr de ce que vous entendez par "simplifié", simplifié de quelle manière? Moins verbeux? Plan de requête moins complexe? Plus de performance? En d'autres termes, quel problème essayez-vous de résoudre?

Quelques idées:

  • Vous pouvez créer une vue pour votre sous-sélection (ou sous-sélectionne si la différence entre les deux est but) qui réduiraient le verbosité. Obtenez le plan de requête de la requête et recherchez les analyses de table.

  • Envisagez d'utiliser l'indexation en texte intégral plutôt que comme une wild card à le début du motif que cette nécessite l'index entier pour être numérisé (en supposant qu'il existe un indice sur la colonne) - si il n'y a pas d'index , puis ajoutez-en un.

+0

J'ai corrigé la requête. Par simplification je veux dire moins répéter ... – Samuel

+0

Voir idée est bonne! l'idée d'index est bonne aussi. – Samuel