2010-10-19 4 views
0

Je travaille avec des données provenant de plusieurs sources sur lesquelles je n'ai aucun contrôle. Ces sources ont tendance à avoir des doublons dans les valeurs «clés». Je dois garder l'une de ces valeurs en double correspondant à une jointure.Exclure les résultats de la jointure où correspondent les clés en double

En utilisant les données suivantes

T1 
| ID | FirstKey | SecondKey | ThirdKey | AdditionalColumns | 
+----+----------+-----------+----------+---------------------+ 
| 01 | Prod1 | ABC1  | 201  | Jun 2010, A, 101 | 
| 02 | Prod2 | DEF2  | 202  | May 2009, A, 101 | 
| 03 | Prod2 | DEF2  | 202  | May 2010, S, 101 | 
| 04 | Prod3 |   | 206  | Jun 2010, A, 103 | 
| 05 | Prod4 |   | 207  | Jun 2011, S, 103 | 


T2 
| ID | FirstKey | SecondKey | ThirdKey | AdditionalColumns | 
+----+----------+-----------+----------+---------------------+ 
| 01 | Prod1 | ABC1  | 201  | Jun 2010, A, 101 | 
| 02 | Prod2 | DEF2  |   | May 2009, A, 101 | 
| 03 | Prod2 | DEF2  | 202  | May 2010, S, 101 | 
| 04 | Prod3 |   |   | Jun 2010, A, 103 | 
| 05 | Prod4 |   | 207  | Jun 2011, S, 103 | 
| 06 | Prod1 | ABC1  | 201  | Jun 2010, T, 101 | 

Maintenant, si nous faisons la requête:

SELECT 
     T1.FirstKey, T1.SecondKey, T1.ThirdKey, 
     T2.FirstKey, T2.SecondKey, T2.ThirdKey, 
     T1.AdditionalColumns, T2.AdditionalColumns 
FROM 
     T1 JOIN T2 ON T1.FirstKey = T2.FirstKey 
      AND T1.SecondKey = T2.SecondKey 
      AND T1.SecondKey IS NOT NULL 
UNION 
SELECT 
     T1.FirstKey, T1.SecondKey, T1.ThirdKey, 
     T2.FirstKey, T2.SecondKey, T2.ThirdKey, 
     T1.AdditionalColumns, T2.AdditionalColumns 
FROM 
     T1 JOIN T2 ON T1.FirstKey = T2.FirstKey 
      AND T1.ThirdKey = T2.ThirdKey 
      AND T1.SecondKey IS NULL 

Nous obtenons les résultats suivants

FirstKey SecondKey ThirdKey FirstKey SecondKey ThirdKey AdditionalColumns AdditionalColumns 
-------- --------- -------- -------- --------- -------- ----------------- ----------------- 
Prod1  ABC1  201  Prod1  ABC1  201  Jun 2010, A, 101 Jun 2010, A, 101 
Prod1  ABC1  201  Prod1  ABC1  201  Jun 2010, A, 101 Jun 2010, T, 101 
Prod2  DEF2  202  Prod2  DEF2  202  May 2009, A, 101 May 2010, S, 101 
Prod2  DEF2  202  Prod2  DEF2  202  May 2010, S, 101 May 2010, S, 101 
Prod4  NULL  207  Prod4  NULL  207  Jun 2011, S, 103 Jun 2011, A, 103 

J'ai besoin de la requête pour ne retourner les avec un match faisant autorité. par exemple. Seulement 1 match entre les tables.

FirstKey SecondKey ThirdKey FirstKey SecondKey ThirdKey AdditionalColumns AdditionalColumns 
-------- --------- -------- -------- --------- -------- ----------------- ----------------- 
Prod4  NULL  207  Prod4  NULL  207  Jun 2011, S, 103 Jun 2011, A, 103 

Existe-t-il un moyen de le faire dans JOIN?

Actuellement, je peux obtenir des uniques en faisant CTE pour chaque table qui garantit l'unicité sur les clés utilisées dans la jointure. Cela fonctionne, mais est moche et ajoute un travail important à la requête.

Existe-t-il une autre façon de faire cette jointure qui exclura les correspondances en double? Cela suppose que je ne peux pas exclure par programme l'une des lignes dupliquées en fonction des données AdditionalColumns. Je cours dans ceci encore et encore ainsi la méthode de CTE semble juste kludgey car il doit être un problème qui a été résolu.

Répondre

1

Comment l'utilisation de GROUP BY autour de votre requête:

SELECT T1.FirstKey, T1.SecondKey, T1.ThirdKey, T2.FirstKey, T2.SecondKey, T2.ThirdKey, T1.AdditionalColumns, T2.AdditionalColumns, COUNT(*) 
FROM (
SELECT 
     T1.FirstKey, T1.SecondKey, T1.ThirdKey, 
     T2.FirstKey, T2.SecondKey, T2.ThirdKey, 
     T1.AdditionalColumns, T2.AdditionalColumns 
FROM 
     T1 JOIN T2 ON T1.FirstKey = T2.FirstKey 
      AND T1.SecondKey = T2.SecondKey 
      AND T1.SecondKey IS NOT NULL 
UNION 
SELECT 
     T1.FirstKey, T1.SecondKey, T1.ThirdKey, 
     T2.FirstKey, T2.SecondKey, T2.ThirdKey, 
     T1.AdditionalColumns, T2.AdditionalColumns 
FROM 
     T1 JOIN T2 ON T1.FirstKey = T2.FirstKey 
      AND T1.ThirdKey = T2.ThirdKey 
      AND T1.SecondKey IS NULL 
) 
GROUP BY T1.FirstKey, T1.SecondKey, T1.ThirdKey, T2.FirstKey, T2.SecondKey, T2.ThirdKey, T1.AdditionalColumns, T2.AdditionalColumns 
HAVING COUNT(*) = 1; 
0

Une suggestion.

Faites tout votre sélection une sous-requête. Appelons-SubQ

Ensuite, vous le faites comme ceci:

SELECT * 
FROM (SUBQ) 
GROUP BY `ThirdKey` 
HAVING COUNT(*) = 1 
Questions connexes