2010-03-28 6 views
19

Ma question est assez similaire à Restricting a LEFT JOIN, avec une variation.Supprimer des doublons de gauche OUTPUT JOIN

En supposant que j'ai une table SHOP et une autre table EMPLACEMENT. L'emplacement est une sorte de table enfant de la table SHOP, qui a deux colonnes d'intérêt, l'une est une clé de division (l'appelant juste KEY) et un numéro "SHOP". Cela correspond au numéro "NO" dans la table SHOP.

J'ai essayé cette jointure externe gauche:

SELECT S.NO, L.KEY 
FROM SHOP S 
LEFT OUTER JOIN LOCATN L ON S.NO = L.SHOP 

mais je reçois beaucoup de doublons car il y a beaucoup d'endroits qui appartiennent à un seul magasin. Je veux les éliminer et juste obtenir une liste de "shop, clé" entrées sans doublons.

Les données sont correctes, mais les doublons apparaissent comme suit:

SHOP  KEY 
1  XXX 
1  XXX 
2  YYY 
3  ZZZ 
3  ZZZ etc. 

Je voudrais que les données apparaissent comme ceci:

SHOP  KEY 
1  XXX 
2  YYY 
3  ZZZ etc. 

table SHOP:

NO 
1  
2  
3  

LOCALISATION table:

LOCATION SHOP KEY 
    L-1  1 XXX 
    L-2  1 XXX 
    L-3  2 YYY 
    L-4  3 YYY 
    L-5  3 YYY 

(Oracle 10g Database)

+0

Vous ne devriez pas obtenir de doublons, bien que, comme vous l'avez indiqué, vous pouvez obtenir plus d'une clé pour un magasin si vous avez plus d'un enregistrement de localisation pour le magasin. Veuillez expliquer ou donner un exemple de ce que vous entendez par "duplicata". –

+1

@Marcus J'ai pensé la même chose au début, mais je suppose que plusieurs emplacements peuvent avoir la même clé de division. –

+0

@ Marcus & Martin: ah je ne pense pas que je l'ai fait comprendre. Oui Plusieurs emplacements peuvent et ont une même clé de division. (À proprement parler, divnkey est le parent de la boutique, donc la hiérarchie va comme ce Divnkey> Shop> location). J'essaie de remplir la table de Shop avec les données de clé de division appropriées. Cela peut sembler bizarre, mais c'est un processus ponctuel et j'essayais de générer des scripts de mise à jour pour la table SHOP à partir des données de la table LOCATION - via une commande 'update shop set divnkey = ....'. Je ne voulais pas compliquer la question alors mettez un simple sélectionner. –

Répondre

24

Vous devez GROUP BY S.No '& « L.KEY »

SELECT S.NO, L.KEY 
FROM SHOP S 
LEFT OUTER JOIN LOCATN L 
ON S.NO = L.SHOP 
GROUP BY S.NO, L.KEY 
+0

+1 pour utiliser 'GROUP BY' qui est équivalent à' DISTINCT' sur Oracle http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212 peut parfois être plus rapide sur d'autres moteurs, par exemple Postgres (en utilisant des hachages au lieu de trier.) – vladr

+0

Ok, vous venez de me faire sentir vraiment stupide. Cela fonctionne parfaitement. Merci. Mais tous les commentaires supplémentaires sur pourquoi le groupe par est nécessaire du tout lorsque l'extérieur gauche est censé prendre soin de cela. Comme dans j'essaie de comprendre comment fonctionne l'extérieur gauche. –

+0

@Kaushik: Un LEFT OUTER JOIN n'est pas équivalent et n'implique pas GROUP BY ou DISTINCT. Le LEFT JOIN prend toutes les lignes de la première table (gauche) et joint toutes les lignes de la table de droite (seconde) où la condition de jointure est satisfaite. Dans une jointure left * outer *, si aucune donnée trouvée dans la table de droite ne correspond aux données de la table de gauche, les données de la table de gauche sont toujours retournées avec des valeurs NULL pour toutes les données de table de droite. Aucun groupement n'est exprimé ou implicite. Personnellement, j'aurais utilisé DISTINCT car je pense qu'il spécifie plus clairement l'intention, mais YMMV. –

7

EDIT Après la mise à jour dans votre scénario

Je pense que vous devriez être en mesure de le faire avec un simple sous requête (bien que je ne l'ai pas testé contre un Base de données Oracle). Quelque chose comme ce qui suit

UPDATE shop s 
SET divnkey = (SELECT DISTINCT L.KEY FROM LOCATN L WHERE S.NO = L.SHOP) 

ci-dessus soulèvera une erreur dans le cas d'un magasin étant associé à des endroits qui sont dans plusieurs divisions.

Si vous voulez juste d'ignorer cette possibilité et sélectionner un arbitraire dans ce cas, vous pouvez utiliser

UPDATE shop s 
SET divnkey = (SELECT MAX(L.KEY) FROM LOCATN L WHERE S.NO = L.SHOP) 
+0

Nice :) C'est pourquoi il est important d'avoir plus d'un angle. Merci Martin, votre solution satisfait très certainement mon besoin sous-jacent (Mais l'autre réponse s'occupe spécifiquement de supprimer les doublons, donc de devoir marquer celle-là). Salutations –

6

J'ai aussi eu ce problème mais je n'ai pas pu utiliser GROUP BY pour le réparer car je retournais aussi des champs de type TEXT. (Idem pour l'utilisation de DISTINCT).

Ce code m'a donné doublons:

select mx.*, case isnull(ty.ty_id,0) when 0 then 'N' else 'Y' end as inuse 
from master_x mx 
left outer join thing_y ty on mx.rpt_id = ty.rpt_id 

je fixe en le réécrivant ainsi:

select mx.*, 
case when exists (select 1 from thing_y ty where mx.rpt_id = ty.rpt_id) then 'Y' else 'N' end as inuse 
from master_x mx 

Comme vous pouvez le voir, je me fichais des données au sein de la 2e table (thing_y), juste s'il y avait plus de zéro matches sur le rpt_id en son sein. (FYI: rpt_id n'était pas non plus la clé primaire sur la 1ère table, master_x).

Questions connexes