2010-04-16 9 views
24

Mam tabelę nazw i adresów, która zawiera kolumnę z kodem pocztowym. Chcę usunąć spacje z kodów pocztowych i wybrać te, które pasują do określonego wzorca. Próbuję to (nieco uproszczone) w T-SQL na SQL Server 2005:WYBIERZ z Wymień()

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

Ale pojawia się następujący błąd;

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

Jeśli usunąć klauzulę gdzie mogę uzyskać listę kodów pocztowych bez spacji, która jest, co chcesz wyszukać. Jak mam się do tego podejść? Co ja robię źle?

+1

można utworzyć zmaterializowanej indeksowany widok, gdzie Zamień będzie precomputed i częścią indeksu fizycznego, i można wyszukiwania off, że bez zmiany oryginalnych danych lub stole. –

Odpowiedz

32

Nie należy używać skrótu (P) bezpośrednio w klauzuli WHERE.

Można ponownie użyć tej samej REPLACE logikę w klauzuli WHERE:

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

Albo użyć aliasem zapytanie sub jak opisano w odpowiedzi Nicka.

+0

To nie zadziała, jeśli "Kod pocztowy" zaczyna się od spacji. –

+0

To nie robi tego, co potrzebuje OP ... próbuje użyć 'LIKE' na wersji bez odstępów ... –

+0

Dzięki Oded! To działa dla mnie. –

11

można odwoływać się w ten sposób, jeśli owinąć zapytanie, tak:

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

Pamiętaj, aby podać owinięte Wybierz alias, nawet nieużywane (SQL Server nie pozwala na to bez jednego IIRC)

2

Tworzysz alias P, a później w klauzuli where używasz tego samego, właśnie to powoduje problem. Nie używaj P w where, spróbuj zamiast tego:

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

Trzeba powtórzyć swój wyraz wszędzie chcesz go używać:

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

lub możesz zrobić to podzapytanie

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

Aby rozwinąć Oded's answer, twój model koncepcyjny wymaga tutaj niewielkiej korekty. Aliasowanie nazw kolumn (AS) na liście SELECT dzieje się bardzo późno podczas przetwarzania SELECT, dlatego też nazwy aliasów nie są dostępne w klauzulach WHERE. W rzeczywistości jedyną rzeczą, która się dzieje, gdy kolumna aliasing jest sortowanie, dlatego (zacytować docs na SELECT):

column_alias mogą być używane w klauzuli ORDER BY. Jednak nie można go użyć w klauzuli WHERE, GROUP BY lub HAVING.

Jeśli masz zawiłe wyraz w liście SELECT, można się martwić o nim „jest oceniany dwa razy”, gdy pojawi się na liście SELECT i (powiedzmy) A WHERE klauzula - jednak silnik zapytanie jest mądry wystarczy, żeby się dowiedzieć, co się dzieje.Jeśli chcesz uniknąć wyrażenie pojawia się dwa razy w zapytaniu, można zrobić coś jak

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

który unika some_complicated_expression fizycznie pojawiające się dwukrotnie.

+0

+1 Dzięki za jasne wyjaśnienie Aakash. Myślę, że podświadomie unikałem powtarzania Replace(); a to prawdopodobnie powstrzymało mnie przed znalezieniem właściwego rozwiązania. Dzięki! –

+0

To powinna być poprawna odpowiedź. Zasadniczo WHERE jest przetwarzany przed SELECT. W związku z tym klauzula WHERE nie byłaby świadoma istniejącej kolumny, która jest aliasowana jako P. Ponadto, ponieważ kolumna P jest wartością obliczoną, zastosowanie podejścia podkwerendy byłoby jednym z rozwiązań w porównaniu do wykonywania Replace() dwukrotnie . – 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

Jeśli chcesz mieć jakąkolwiek nadzieję na użycie indeksu, przechowuj dane w spójny sposób (z usuniętymi spacjami). Po prostu usuń spacje lub dodaj utrwaloną kolumnę obliczeniową. Następnie możesz po prostu wybrać z tej kolumny i nie musisz dodawać całego miejsca, usuwając obciążenie przy każdym uruchomieniu zapytania.

dodać utrzymywały kolumna obliczana:

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

po prostu naprawić kolumnę poprzez usunięcie spacji użyć:

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

teraz można szukać w ten sposób, albo wybrać można użyć indeksu:

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

lub

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

Dzięki za poświęcenie czasu, aby dać to świetne wyjaśnienie, KM. Niestety, omawiana baza danych jest częścią "starego" systemu, który muszę traktować jako tylko do odczytu. Ale doceniam twój punkt widzenia na indeksowanie. Nie wiedziałem o utrwalonych kolumnach obliczeniowych - więc nauczyłem się czegoś. Dzięki! –

0

to będzie działać:

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