2010-04-17 14 views
0

Situation hypothétique: Je travaille pour une entreprise de fabrication de panneaux personnalisée, et certains de nos clients ont soumis plus de modèles de panneaux que J'utilise actuellement. Je veux savoir quels signes n'ont jamais été utilisés.sybase - valeurs d'une table qui ne se trouvent pas sur une autre, aux extrémités opposées d'une jointure à 3 tables

3 tables impliquées:

Tableau A - signes pour une entreprise

sign_pk (unique) | company_pk | signature_description
1 -------------------- 1 ---------------- petit
2 ----- --------------- 1 ---------------- grand
3 -------------- ------ 2 ---------------- moyen
4 -------------------- 2 - -------------- jumbo
5 -------------------- 3 ----------- ----- bannière

tableau B - sites de l'entreprise

company_pk | company_location (unique)
1 ------ | ------ 987
1 ------ | ------ 876
2 ------ | - ---- 456
2 ------ | ------ 123

tableau C - signes en des endroits (il est un peu exagéré, mais chaque rangée peut avoir 2 signes, et c'est une relation de un à plusieurs de l'emplacement de l'entreprise à des signes aux endroits)

company_location | front_sign | back_sign
987 ------------ 1 ------------ 2
987 ------------ 2 ---- -------- 1
876 ------------ 2 ------------ 1
456 --------- --- 3 ------------ 4
123 ------------ 4 ------------ 3

Ainsi, a.company_pk = b.company_pk et b.company_location = c.company_location. Ce que je veux essayer et trouver, c'est comment interroger et revenir que sign_pk 5 n'est à aucun endroit. Interroger chaque sign_pk par rapport à toutes les valeurs front_sign et back_sign est peu pratique, car toutes les tables ont des millions de lignes. Le tableau a est indexé sur sign_pk et company_pk, la table b sur les deux champs et la table c uniquement sur les emplacements de l'entreprise. La façon dont j'essaie de l'écrire est la suivante: «Chaque signe appartient à une entreprise, alors trouvez les signes qui ne sont pas le signe avant ou arrière à l'un des emplacements appartenant à l'entreprise liée à ce signe.

Mon plan initial était: juste
Select a.sign_pk
from a, b, c
where a.company_pk = b.company_pk
and b.company_location = c.company_location
and a.sign_pk *= c.front_sign
group by a.sign_pk having count(c.front_sign) = 0

pour faire le signe avant, puis répéter pour le dos, mais cela ne fonctionnera pas, car c est un élément interne d'une jointure externe, et aussi une jointure interne. Tout ce truc est assez alambiqué, mais si quelqu'un peut le comprendre, je serai votre meilleur ami.

Répondre

1

Que diriez-vous quelque chose comme ceci:

SELECT DISTINCT sign_pk 
    FROM table_a 
    WHERE sign_pk NOT IN 
    ( 
     SELECT DISTINCT front_sign sign 
     FROM table_c 
     UNION 
     SELECT DISTINCT rear_sign sign 
     FROM table_c 
    ) 
+0

Interroger chaque sign_pk par rapport à toutes les valeurs de front_sign et de back_sign est peu pratique, car toutes les tables ont des millions de lignes et les colonnes front_sign et back_sign ne sont pas indexées. Cela semble conduire à deux balayages de la table c. –

+0

LazyBob, il va être difficile de concevoir une solution efficace étant donné la mauvaise conception des tables hypothétiques. Si vous dessinez les tables, vous verrez que les relations forment un triangle. La table "Signes aux emplacements" ne doit contenir que 1 sign_pk et avoir une colonne "type de signe". – AdamH

+0

dcp, je pense que le vôtre est probablement la meilleure solution possible compte tenu de la structure de la table. Je ne voudrais pas déranger avec le "distinct" * au sein de la clause IN, il force le travail inutile sur sybase pour aucune amélioration réelle. – AdamH

0

jointure externe ANSI est votre ami ici.* = A la sémantique louches et doit être évitée

select distinct a.sign_pk, a.company_pk 
from a join b on a.company_pk = b.company_pk 
left outer join c on b.company_location = c.company_location 
        and (a.sign_pk = c.front_sign or a.sign_pk = c.back_sign) 
where c.company_location is null 

Notez que le clause est un filtre sur les lignes renvoyées par la jointure, il dit: « faire les jointures, mais donnez-moi seulement les lignes n'a pas à se joindre à c »

jointure externe est presque toujours plus rapide que NOT EXISTS et NOT IN

0

Je serais tenté de créer une table temporaire pour la jointure interne puis jointure externe qui. Mais cela dépend vraiment de la taille de vos ensembles de données. Oui, la conception du schéma est défectueuse, mais nous ne pouvons pas toujours résoudre ce problème!