web-dev-qa-db-fra.com

SELECT avec un remplacement ()

J'ai une table de noms et d'adresses, qui comprend une colonne de code postal. Je souhaite supprimer les espaces des codes postaux et sélectionner ceux qui correspondent à un modèle particulier. J'essaie ceci (un peu simplifié) dans T-SQL sur SQL Server 2005:

SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE P LIKE 'NW101%'

Mais je reçois l'erreur suivante;

Msg 207, Level 16, State 1, Line 3
Invalid column name 'P'.

Si je supprime la clause WHERE, je reçois une liste de codes postaux sans espaces, ce que je souhaite rechercher. Comment devrais-je aborder cela? Qu'est-ce que je fais mal?

28
Andy Johnson

N'utilisez pas l'alias (P) directement dans votre clause WHERE

Vous pouvez utiliser à nouveau la même logique REPLACE dans la clause WHERE:

SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%'

Ou utilisez une sous-requête avec alias comme décrit dans les réponses de Nick.

36
Oded

Vous pouvez faire référence à cette façon si vous enroulez la requête, comme ceci:

SELECT P
FROM (SELECT Replace(Postcode, ' ', '') AS P
      FROM Contacts) innertable
WHERE P LIKE 'NW101%'

Assurez-vous de donner à la sélection enveloppée un alias, même inutilisé (SQL Server ne le permet pas sans un IIRC)

11
Nick Craver

Vous créez un alias P et plus tard dans la clause where vous utilisez le même, c’est ce qui crée le problème. N'utilisez pas P dans where, essayez plutôt ceci:

SELECT Replace(Postcode, ' ', '') AS P FROM Contacts
WHERE Postcode LIKE 'NW101%'
3
Sarfraz

Pour développer la réponse de Oded , votre modèle conceptuel nécessite un léger ajustement ici. La création d'alias de noms de colonnes (clauses AS dans la liste SELECT) intervient très tard dans le traitement d'une SELECT, raison pour laquelle les noms d'alias ne sont pas disponibles pour les clauses WHERE. En fait, la seule chose qui se passe après le repliement des colonnes est le tri, ce qui explique pourquoi (pour citer les docs sur SELECT):

column_alias peut être utilisé dans une clause ORDER BY. Cependant, il ne peut pas être utilisé dans une clause WHERE, GROUP BY ou HAVING

Si vous avez une expression compliquée dans la liste SELECT, vous craignez peut-être qu'elle soit «évaluée deux fois» lorsqu'elle apparaît dans la liste SELECT et (disons) une clause WHERE - cependant, le moteur de requête est assez intelligent pour comprendre ce qui se passe sur. Si vous voulez éviter que l'expression apparaisse deux fois dans votre requête, vous pouvez faire quelque chose comme:

SELECT c1, c2, c3, expr1
FROM
    ( SELECT c1, c2, c3, some_complicated_expression AS expr1 ) inner
WHERE expr1 = condition

ce qui évite que some_complicated_expression apparaisse physiquement deux fois.

3
AakashM

si vous souhaitez avoir un espoir d'utiliser un index, stockez les données de manière cohérente (sans les espaces). Supprimez simplement les espaces ou ajoutez une colonne calculée persistante. Vous pouvez alors simplement sélectionner dans cette colonne et ne pas avoir à ajouter tout l'espace en supprimant la surcharge chaque fois que vous exécutez votre requête.

ajoutez une colonne calculée PERSISTED:

ALTER TABLE Contacts ADD PostcodeSpaceFree AS Replace(Postcode, ' ', '') PERSISTED 
go
CREATE NONCLUSTERED INDEX IX_Contacts_PostcodeSpaceFree 
ON Contacts (PostcodeSpaceFree) --INCLUDE (covered columns here!!)
go

pour simplement corriger la colonne en supprimant les espaces, utilisez:

UPDATE Contacts
    SET Postcode=Replace(Postcode, ' ', '')

maintenant vous pouvez chercher comme ceci, soit sélectionnez peut utiliser un index:

--search the PERSISTED computed column
SELECT 
    PostcodeSpaceFree 
    FROM Contacts
    WHERE PostcodeSpaceFree  LIKE 'NW101%'

ou

--search the fixed (spaces removed column)
SELECT 
    Postcode
    FROM Contacts
    WHERE PostcodeLIKE 'NW101%'
3
KM.
SELECT *
FROM Contacts
WHERE ContactId IN
    (SELECT a.ContactID
    FROM
        (SELECT ContactId, Replace(Postcode, ' ', '') AS P
        FROM Contacts
        WHERE Postcode LIKE '%N%W%1%0%1%') a
    WHERE a.P LIKE 'NW101%')
2
Anthony Faull

Vous devez répéter votre expression partout où vous voulez l'utiliser:

SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%'

ou vous pouvez en faire une sous-requête

select P
from (
SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
) t
WHERE P LIKE 'NW101%'
2

Cela fonctionnera:

SELECT Replace(Postcode, ' ', '') AS P
FROM Contacts
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%'
0
Ibama