2010-10-07 7 views
1

semble simple, mais je suis coincéSQL JOIN question (encore un autre)

Table A     Table B 

col_a col_b   col_a col_c 
1  b    1  c 
2  c    2  d 
3  z    3  a 
4  d    4  e 
33  a    5  k 
         6  l 
         33  b 
         33  b 

Je veux rejoindre le tableau A avec B:

select * from A inner join B on A.col_a = B.col_a 

Je comptais obtenir 5 dossiers comme résultat.

Expected join result   ** Actual result ** 

col_a col_b col_c col_x[n]...  col_a col_b col_c col_y[n]... 
1  b  c  ...     1  b  c ... 
2  c  d  ...     2  c  d ... 
3  z  a  ...     3  z  a ... 
4  d  e  ...     4  d  e ... 
33  a  b  ...     33 a  b ... 
             33 a  b ... 

Pourquoi MySQL a-t-il correspondu à 33 deux fois? Parce qu'ils sont 2 valeurs avec 33 dans la table B.

Ce que je veux cependant, est juste un enregistrement avec la même valeur dans col_a. Comment je fais ça? Je suis mise à jour la conception des tables pour inclure plus de colonnes qui contiennent des données non identiques, car elles ont été posées plus de questions que de problèmes résolus. Quoi qu'il en soit, la réponse à cela est d'utiliser GROUP BY, mais la pénalité de performance est énorme, en particulier sur une table qui contient plus de 50 millions d'enregistrements (et de plus en plus). Cependant, la meilleure approche pour résoudre mon problème consistait à utiliser une instruction composée (en utilisant UNION ALL) pour chaque valeur distincte dans col_a. L'avantage de la performance était x5 ~ x10 plus rapide !!

Répondre

4

Vous avez 33 deux fois dans le tableau B.

Soit SELECT DISTINCT ou GROUP BY col_a, ...:

SELECT DISTINCT * 
FROM A 
JOIN B ON (A.col_a = B.col_a) 
; 

ou

SELECT * 
FROM  A 
JOIN  B ON (A.col_a = B.col_a) 
GROUP BY col_a, col_b, col_c 
; 

Vous devez nettoyer cette table, cependant. Selon le nombre d'occurrences d'une ligne répétée, il pourrait être plus rapide d'utiliser une sous-requête:

SELECT * 
FROM A 
JOIN (select distinct * from B) AS C 
     ON (A.col_a = C.col_a) 
; 
+0

notez l'absence de 'INNER' comme' JOIN' par lui-même est un 'INNER JOIN' par défaut. – vol7ron

+0

la sous-requête n'est pas conseillée et dépend du plan de requête de la base de données. mais si vous avez ** beaucoup ** d'entrées en double dans les deux tables (quelle qu'en soit la raison), alors la sous-requête réduira le travail impliqué. – vol7ron

+0

GROUP BY semble faire l'affaire (bien qu'il y ait une pénalité de performance)! –

2

La réponse sale & rapide est:

select DISTINCT * from A inner join B on A.col_a = B.col_a 

Mais la vraie question est, pourquoi avez-vous avoir deux entrées identiques dans le tableau B?

Généralement, lorsque vous utilisez DISTINCT, cela indique un problème dans votre modèle de données.

+0

Tous les enregistrements ne sont pas identiques colonne à colonne, car il existe un champ d'incrémentation automatique dans les tables A et B.Il s'agit essentiellement d'une application de journalisation et le problème réel est plus complexe, mais les enregistrements "en double" sont inévitables :(Quoi qu'il en soit, l'utilisation de DISTINCT * n'aide pas –

+0

@Theo Zographo: "La clé primaire artificielle incrémente automatiquement les doublons réels" n'est pas un nouvelle histoire :( – onedaywhen