2010-06-12 4 views
3

Lors de l'utilisation d'une jointure SQL, est-il possible de conserver uniquement les lignes ayant une seule ligne pour la table de gauche?Le filtre se duplique dans la jointure SQL

Par exemple:

select * from A, B where A.id = B.a_id; 

a1 b1 
a2 b1 
a2 b2 

Dans ce cas, je veux supprimer tout sauf la première ligne, où une seule rangée de A apparié exactement 1 rang de B.

J'utilise MySQL .

Répondre

4

Cela devrait fonctionner MySQL:

select * from A, B where A.id = B.a_id GROUP BY A.id HAVING COUNT(*) = 1; 

Pour ceux d'entre vous de ne pas utiliser MySQL, vous aurez besoin d'utiliser des fonctions d'agrégation (comme min() ou max()) sur toutes les colonnes (sauf A. id) afin que votre moteur de base de données ne se plaint pas.

+0

Cela ne fonctionne pas correctement si B a plus de 1 ligne correspondante. Vous devez supprimer la clause HAVING et cela devrait être correct (bien que je recommande définitivement d'utiliser toujours des fonctions d'agrégat pour les colonnes non-GROUPED). – sqlvogel

+0

excuses. J'ai l'air d'avoir mal lu ce qui était recherché. On dirait que votre requête est bonne et pas la mienne, mais au cas où ça vous aiderait, je laisserai la mienne pour le moment :) – sqlvogel

0

Il est utile si vous spécifiez les clés de vos tables lorsque vous posez une question comme celle-ci. Il ne ressort pas clairement de votre exemple quelle pourrait être la clé de B (en supposant qu'elle en ait une).

Voici une solution possible en supposant que ID est une clé candidate du tableau B.

SELECT * 
FROM A, B 
WHERE B.id = 
(SELECT MIN(B.id) 
    FROM B 
    WHERE A.id = B.a_id); 
0

D'abord, je vous conseille d'utiliser la syntaxe JOIN au lieu de la syntaxe obsolète de la séparation des tables par des virgules. En second lieu, si A.id est la clé primaire de la table A, alors vous devez vous inspectez seule table B des doublons:

Select ... 
From A 
    Join B 
     On B.a_id = A.id 
Where Exists (
       Select 1 
       From B B2 
       Where B2.a_id = A.id 
       Having Count(*) = 1 
       ) 
0

On évite ainsi le coût de comptage des lignes correspondantes, ce qui peut être coûteux pour les grandes tables.

Comme d'habitude, lors de la comparaison de diverses solutions possibles, il est suggéré de comparer/comparer les plans d'exécution.

select 
    * 
from 
    A 
    join B on A.id = B.a_id 
where 
    not exists (
    select 
     1 
    from 
     B B2 
    where 
     A.id = b2.a_id 
     and b2.id != b.id 
)