2010-04-16 14 views
24

Tengo una tabla de nombres y direcciones, que incluye una columna de código postal. Quiero quitar los espacios de los códigos postales y seleccionar cualquiera que coincida con un patrón en particular. Estoy tratando esto (simplificado un poco) en T-SQL en SQL Server 2005:SELECCIONAR con un Reemplazar()

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

pero me da el siguiente error;

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

Si quito la cláusula donde consigo una lista de códigos postales sin espacios, que es lo que desea buscar. ¿Cómo debería abordar esto? ¿Qué estoy haciendo mal?

+1

se puede crear una vista indizada materializado, donde se precalculados Reemplazar y parte de un índice físico, y usted podría buscar fuera que sin cambiar los datos o la mesa de originales. –

Respuesta

32

No use el alias (P) en su cláusula WHERE directamente.

También se puede usar la misma lógica REPLACE de nuevo en la cláusula WHERE:

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

O utilizar una consulta sub alias, tal como se describe en las respuestas de Nick.

+0

Esto no funcionará si 'Código postal' comienza con espacios. –

+0

Esto no hace lo que el OP necesita ... está tratando de usar un 'LIKE' en la versión sin espaciado ... –

+0

Gracias Oded! Funciona para mi. –

11

Puede hacer referencia es de esa manera si se coloca la consulta, así:

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

Asegúrese de darle a la envuelta seleccionar un alias, incluso sin usar (SQL Server no permite que sin uno IIRC)

2

Usted está creando un alias P y más tarde en la cláusula where que está utilizando igual, eso es lo que está creando el problema. No utilice P en where, probar este lugar:

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

Hay que repetir la expresión de todo el mundo que desee utilizarlo:

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

o puede que sea una sub consulta

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

Para ampliar en Oded's answer, su modelo conceptual necesita un ligero ajuste aquí. El alias de los nombres de columna (AS en la lista SELECT) ocurre muy tarde en el procesamiento de un SELECT, por lo que los nombres de alias no están disponibles para las cláusulas WHERE. De hecho, la única cosa que sucede después de la columna de alias es la clasificación, por lo que (para citar los documentos en SELECT):

column_alias se puede utilizar en una cláusula ORDER BY. Sin embargo, no se puede usar en una cláusula WHERE, GROUP BY o HAVING.

Si usted tiene una expresión enrevesada en la lista SELECT, usted puede estar preocupado por que 'se está evaluando dos veces' cuando aparece en la lista SELECT y (por ejemplo) una cláusula WHERE - sin embargo, el motor de consulta es inteligente lo suficiente como para resolver lo que está pasando.Si desea evitar que la expresión aparece dos veces en la consulta, se puede hacer algo como

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

que evita some_complicated_expression que aparece físicamente en dos ocasiones.

+0

+1 Gracias por la clara explicación de Aakash. Creo que, de forma subconsciente, estaba evitando repetir el reemplazo(); y esto probablemente me impidió ver la solución correcta. ¡Gracias! –

+0

Esta debería haber sido la respuesta correcta. Fundamentalmente, DONDE se está procesando antes de SELECCIONAR. Por lo tanto, la cláusula WHERE no conocería la existencia de la columna que tiene un alias como P. Además, dado que la columna P es un valor calculado, usar el enfoque de subconsulta sería una de las soluciones en comparación con hacer Replace() dos veces . – frostshoxx

2
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%') 
3

si desea tener alguna esperanza de utilizar un índice, almacene los datos de forma coherente (con los espacios eliminados). Elimine los espacios o agregue una columna calculada persistente. Luego, puede seleccionar desde esa columna y no tener que agregar todo el espacio que elimina la sobrecarga cada vez que ejecuta su consulta.

añadir un PERSISTED columna calculada:

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

simplemente fijar la columna mediante la eliminación de los espacios de uso:

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

Ahora puede buscar este tipo, ya sea de selección puede usar un índice:

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

o

--search the fixed (spaces removed column) 
SELECT 
    Postcode 
    FROM Contacts 
    WHERE PostcodeLIKE 'NW101%' 
+0

Gracias por tomarse el tiempo para dar esta gran explicación, KM. Lamentablemente, la base de datos en cuestión es parte de un sistema "heredado" que debo tratar como de solo lectura. Pero aprecio tu punto acerca de la indexación. No estaba al tanto de las columnas computadas persistentes, así que aprendí algo. ¡Gracias! –

0

Esto funcionará:

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