2012-05-02 2 views
0

J'ai une requête qui joint des données sur 4 tables pour fournir des données basées sur les résultats de test. La requête fonctionne correctement, à l'exception du fait qu'elle renvoie deux enregistrements identiques pour chaque ligne de données uniques. Si je lance un DISTINCT devant la colonne de la clé primaire (a.id) de l'une des tables de la jointure, cela élimine tous les doublons. Cependant, j'ai lu (et trouvé) que DISTINCT tend à introduire un coup de performance, donc j'espère trouver une solution plus performante, si possible. J'espère que je fais juste quelque chose de stupide avec mes JOINS qui sont facilement réparés. C'est sur postgresql-9.0.x, et oui je suis conscient que si je mis à jour vers 9.1.x alors je pourrais probablement faire un 'group by a.id', mais pour l'instant je suis coincé sur 9.0.x.Élimination des enregistrements en double renvoyés par une requête JOIN SQL sur postgresql

est ici la requête:

SELECT a.id,a.suiteid,a.testname 
    ,date_trunc('second',a.last_update) AS last_update 
    ,regexp_replace(p.relname,E'tests','','g') 
    ,o.osname 
FROM smoketests AS a 
    , pg_class AS p 
    , smoke AS t 
    , osversmap AS o 
WHERE a.osversion=o.osversion 
    AND a.suiteid=t.id 
    AND a.tableoid=p.oid 
    AND (a.current_status='FAILED') 
    AND (a.arch='i386') 
    AND (a.os='Darwin') 
    AND a.last_update>'2012-05-01 04:00:00' 
    AND a.last_update<'2012-05-02 14:20:45' 
ORDER BY a.id ; 

qui produit cette sortie:

id | suiteid |  testname  |  last_update  | regexp_replace | osname 
----------+---------+------------------+---------------------+----------------+------------ 
32549818 | 668232 | bug377064  | 2012-05-01 08:38:07 | smoke   | OSX-10.7.x 
32549818 | 668232 | bug377064  | 2012-05-01 08:38:07 | smoke   | OSX-10.7.x 
32549819 | 668232 | funcmem_resize | 2012-05-01 08:38:07 | smoke   | OSX-10.7.x 
32549819 | 668232 | funcmem_resize | 2012-05-01 08:38:07 | smoke   | OSX-10.7.x 
32549820 | 668232 | leitest   | 2012-05-01 08:38:07 | smoke   | OSX-10.7.x 
32549820 | 668232 | leitest   | 2012-05-01 08:38:07 | smoke   | OSX-10.7.x 

Le problème est visible dans la colonne id, où il y a deux de chaque valeur retournée même si a.id est la clé primaire unique de la table de fumée et n'a pas vraiment de doublons. La table 'smoke' a une relation de un à plusieurs avec la table smoketests, mais je suis encore un peu confuse pourquoi je reçois les doublons de tout.

+2

Quelle jointure provoque des doublons? Commencez avec juste "smoketests" et commencez à ajouter vos jointures jusqu'à ce que vous trouviez le coupable. Et veuillez utiliser des jointures explicites ('joindre t on ...' ou 'joindre t using ...') plutôt que des jointures implicites à travers la clause WHERE, beaucoup plus facile à déboguer et éviter les produits croisés de cette façon. –

+0

Est-ce que o.osversion identifie de manière unique une ligne de la table osversmap ou existe-t-il une autre colonne requise pour l'unicité? Que diriez-vous de la colonne d'identification dans la fumée? – kgrittn

+0

Compris. Le problème était que osvermap a une colonne arch, de sorte qu'il y a plus d'une osversion et l'arc diffère. Ajoutant ceci éliminé les doublons: o.arch = a.arch – netllama

Répondre

1

La première chose à faire est d'arrêter de faire des jointures croisées implicites. Ceux-ci rendent beaucoup plus difficile la recherche de ce type de problème. Réécrivez votre requête en tant que:

SELECT a.id,a.suiteid,a.testname 
    ,date_trunc('second',a.last_update) AS last_update 
    ,regexp_replace(p.relname,E'tests','','g') 
    ,o.osname 
FROM smoketests AS a 
JOIN pg_class AS p ON a.tableoid=p.oid 
JOIN smoke AS t ON a.suiteid=t.id 
JOIN osversmap AS o ON a.osversion=o.osversion 
WHERE 
    AND (a.current_status='FAILED') 
    AND (a.arch='i386') 
    AND (a.os='Darwin') 
    AND a.last_update>'2012-05-01 04:00:00' 
    AND a.last_update<'2012-05-02 14:20:45' 
ORDER BY a.id ; 

De là, vous devez trouver ce qui cause le doublon. La fumée provoque-t-elle des doublons? Essayez de renvoyer plus d'enregistrements. Si c'est le cas, supprimez la jointure et remplacez-la par une sous-requête IN.

Questions connexes