2010-08-19 2 views
2

Je dois écrire une requête qui effectue une union entre deux tables avec des données similaires. Les résultats doivent être distincts. Le problème que j'ai est que certains champs qui devraient être les mêmes ne sont pas quand il s'agit de valeurs vides. Certaines sont indiquées comme nulles et d'autres ont des valeurs de chaîne vides. Ma question est, y at-il une meilleure façon d'effectuer la requête suivante? (sans fixer les données réelles pour s'assurer que les valeurs par défaut sont définies, etc) Utilisera le cas Quand un gros coup de performance?Meilleure façon d'écrire une requête de syndication lorsque vous traitez des valeurs de chaîne vide et vide

Select 
    When Column1 = '' Then NULL Else Column1 as [Column1], 
    When Column2 = '' Then NULL Else Column2 as [Column2] 
From TableA 

UNION ALL 

Select 
    When Column1 = '' Then NULL Else Column1 as [Column1], 
    When Column2 = '' Then NULL Else Column2 as [Column2] 
From TableB 

Répondre

2

Je ne pense pas qu'il ferait une différence dans performance, mais NULLIF est une autre façon d'écrire cela et, à mon humble avis, semble un peu plus propre.

Select 
    NULLIF(Column1, '') as [Column1], 
    NULLIF(Column2, '') as [Column2] 
From TableA 

UNION 

Select 
    NULLIF(Column1, '') as [Column1], 
    NULLIF(Column2, '') as [Column2] 
From TableB 
+0

Merci pour la note sur le NULLIF. Quoi de mieux, pour retourner un '' ou NULL. – dretzlaff17

+0

Cela dépend vraiment de ce que vous faites avec les données après l'avoir sélectionné. Encore une fois, aucune différence de performance pour retourner l'un contre l'autre. –

+0

Étant donné que les performances ne sont pas un problème, je dois retourner NULL lorsque '' est trouvé pour un enregistrement. Comme je ne connais pas de logique inverse pour l'IFNULL ou le NULLIF, je pense que je vais garder tel quel. Merci à tous pour votre contribution. – dretzlaff17

1

A Case devrait effectuer bien, mais IsNull est plus naturel dans cette situation. Et si vous recherchez des lignes distinctes, faisant une union au lieu d'un union all accomplira que (grâce à Jeffrey L Whitledge pour avoir signalé):

select IsNull(col1, '') 
,  IsNull(col2, '') 
from TableA 
union 
select IsNull(col1, '') 
,  IsNull(col2, '') 
from TableB 
+0

Je pense que vous l'avez à l'envers. L'OP veut NULL quand la colonne est égale à '', et non l'inverse. –

+0

Votre caractérisation de 'union' est incorrecte pour SQL Server. 'union' supprimera toutes les lignes dupliquées des résultats, quelle que soit leur source. –

+0

@Joe Stefenelli: La façon dont je l'ai lu, l'OP dit juste qu'il veut le même résultat @ Jeffrey L Whitledge: Merci, je ne le savais pas! Réponse éditée – Andomar

0

Vous pouvez garder vos opérations de manipulation séparées de l'union si vous faites ce que vous voulez manipulation (NULL remplace la chaîne vide) dans une vue séparée, puis l'union des vues.

Vous ne devriez pas avoir à appliquer la même manipulation sur les deux ensembles, cependant.

Si c'est le cas, associez-les d'abord, puis appliquez une fois la manipulation sur le jeu unifié résultant.

Le code de manipulation est moitié moins important.

1

Utilisez UNION pour supprimer les doublons - il est plus lent que UNION ALL pour cette fonctionnalité:

SELECT CASE 
     WHEN LEN(LTRIM(RTRIM(column1))) = 0 THEN NULL 
     ELSE column1 
     END AS column1, 
     CASE 
     WHEN LEN(LTRIM(RTRIM(column2))) = 0 THEN NULL 
     ELSE column2 
     END AS column2 
    FROM TableA 
UNION 
SELECT CASE 
     WHEN LEN(LTRIM(RTRIM(column1))) = 0 THEN NULL 
     ELSE column1 
     END, 
     CASE 
     WHEN LEN(LTRIM(RTRIM(column2))) = 0 THEN NULL 
     ELSE column2 
     END 
    FROM TableB 

j'ai changé la logique de revenir NULL si la valeur de la colonne contient un certain nombre d'espaces et aucun contenu réel.

CASE les expressions sont ANSI, et plus personnalisables que la syntaxe NULLIF/etc.

Questions connexes