2010-08-16 7 views
7

J'ai une requête qui est la sélection d'un tas de domaines liés aux noms et adresses des clients, mais cela se résume à:Pourquoi "SELECT DISTINCT a, b FROM ..." renvoie-t-il moins d'enregistrements que "SELECT DISTINCT A + '|' + B DE ... "?

SELECT DISTINCT a, b, c, ... FROM big_dumb_flat_table 

il retourne un tas de dossiers (10986590). Quand je remplace les virgules dans la liste de sélection pour mettre en forme comme un tuyau séparé chaîne concaténée:

SELECT DISTINCT a + '|' + b + '|' + c + '|' + ... FROM big_dumb_flat_table 

il est de retour 248 autres enregistrements. Je me suis assuré qu'il n'y a pas de tuyaux dans aucun des champs qui pourraient visser la fidélité de l'ensemble retourné. Que se passe t-il ici?

+0

Pourriez-vous voir ce que vous obtenez avec 'SELECT a, b, c ... FROM ... GROUPE PAR a, b, c ...' et l'éditer dans votre question? (comme 'DISTINCT' est techniquement un hack (très pratique)) – AakashM

+0

Ajoute également le nombre (*) aux requêtes et vois ce que cela donne – Mark

+2

Je m'attendrais à ce que la requête utilisant la concaténation retourne ** ** moins d'enregistrements, puisque si l'un des les valeurs sont 'null' vous obtiendrez un résultat' null'. – RedFilter

Répondre

10

Les espaces de fin pourraient causer ceci. Pour les comparaisons de chaînes, elles sont ignorées.

CREATE TABLE #T 
(
a varchar(10), 
b varchar(10), 
c varchar(10) 
) 

INSERT INTO #T 
SELECT 'a ' as a, 'b' as b, 'c ' as c union all 
SELECT 'a' as a, 'b' as b, 'c ' as c 

SELECT DISTINCT a, b, c 
FROM #T /*1 result*/ 

SELECT DISTINCT a + '|' + b + '|' + c + '|' 
FROM #T /*2 results*/ 


SELECT DISTINCT LTRIM(RTRIM(a)) + '|' + LTRIM(RTRIM(b)) + '|' + 
       LTRIM(RTRIM(c)) + '|' 
FROM #T /*1 result*/ 
+0

Neat. J'ai couru le code abrégé que vous avez d'abord posté pour voir par vous-même que vous aviez raison et maintenant je suis en train de tester les deux requêtes avec tous les champs enveloppés dans ltrim (rtrim()). Cela devrait éliminer ce problème, non? – clweeks

+0

Et il devrait également gérer les valeurs nulles. – HLGEM

+0

@clweeks - Ces colonnes sont-elles valables? Si c'est le cas, vous devrez vous rappeler de gérer Nulls avec COALESCE ou quelque chose. (NB: Si c'est juste une tâche unique, vous pouvez faire 'SET CONCAT_NULL_YIELDS_NULL OFF' mais pas quelque chose pour le code de production!) –

2

Le sont vraiment pas des scénarios que je peux penser à qui vous obtenir PLUS dossiers, seulement moins. Je simplifierais la requête en sélectionnant uniquement un '+', puis ajouterais plus de colonnes au fur et à mesure.