2010-04-16 87 views
24

我有一个名称和地址表,其中包含一个邮政编码列。我想剥离邮政编码中的空格,并选择与特定模式匹配的任何空格。我试图在SQL Server 2005上的T-SQL中(简化一点):用Replace替换()

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

但我得到以下错误;

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

如果我删除了WHERE子句我得到邮政编码列表没有空间,这就是我想要搜索的内容。我应该如何处理这个问题?我究竟做错了什么?

+1

你可以创建一个物化索引视图,其中替换将被预先计算和物理指标的一部分,你可以搜索过,没有改变原始数据或表格。 – 2010-04-16 13:22:33

回答

32

请勿直接在WHERE子句中使用别名(P)。

您可以在WHERE子句中再次使用相同的REPLACE逻辑:

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

或在尼克的答案中描述使用别名的子查询。

+0

如果“邮政编码”以空格开头,这将不起作用。 – 2010-04-16 10:17:49

+0

这不会做OP所需要的......他正试图在未间隔版本上使用'LIKE' ... – 2010-04-16 10:18:29

+0

感谢Oded!这对我行得通。 – 2010-04-16 13:15:04

11

您可以参考这样,如果你包裹查询,例如:

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

请务必给包裹选择一个别名,即使未使用(SQL Server不允许它没有一个IIRC)

2

您正在创建一个别名P和更高版本的where子句中使用相同的,这就是创建问题。不要在where使用P,试试这个来代替:

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

你要到处重复你的表情,你想使用它:

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

,或者你可以把它的子查询

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

要扩大Oded's answer,您的概念模型需要在这里稍作调整。列名称的混淆(SELECT列表中的AS条款)在处理SELECT时发生得非常晚,这就是为什么别名不可用于WHERE子句的原因。事实上,列走样排序后出现这种情况的唯一的事情,这就是为什么(报价上SELECT的文档):

column_alias可以在ORDER BY子句中使用。但是,它不能用于WHEREGROUP BYHAVING子句中。

如果你在SELECT列表中的令人费解的表情,你可能会担心它被两次评估“,当它出现在SELECT列表(比如说)WHERE条款 - 然而,查询引擎是聪明足以解决正在发生的事情。如果你想避免在您的查询的表达出现两次,你可以这样做

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

避免了some_complicated_expression身体出现两次。

+0

+1感谢您的明确解释Aakash。我认为,不自觉地,我避免重复Replace();这可能阻止我看到正确的解决方案。谢谢! – 2010-04-16 13:22:58

+0

这应该是正确的答案。基本上,在SELECT之前正在处理WHERE。因此,WHERE子句不会意识到被替换为别名的列的存在P. 另外,由于列P是一个计算值,所以使用子查询方法将是与执行两次Replace()相比的解决方案之一。 – frostshoxx 2017-01-31 16:46:30

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

如果您想要使用索引的任何希望,请以一致的方式(删除空格)存储数据。只需删除空格或添加持久计算列,然后您可以从该列中进行选择,而不必在每次运行查询时添加全部空间以消除开销。

添加一个持久化计算列:

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

通过删除空格刚修好的列中使用:

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

现在你可以搜索这样的,要么选择可以使用索引:

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

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

感谢您抽出宝贵的时间来解释,KM。不幸的是,有问题的数据库是“遗留”系统的一部分,我必须将其视为只读。但是,我很欣赏你关于索引的观点。我不知道持续计算的列 - 所以我学到了一些东西。谢谢! – 2010-04-16 13:18:38

0

这将工作:

SELECT Replace(Postcode, ' ', '') AS P 
FROM Contacts 
WHERE Replace(Postcode, ' ', '') LIKE 'NW101%' 
相关问题