如何提取美国邮政编码和检查范围

时间:2016-01-07 13:55:24

标签: sql sql-server-2008 alias

我有一张地址表,其中包含来自美国和加拿大的邮政编码。在我们的系统中,我们根据邮政编码范围分配区域,因此我需要提取美国地址并检查它们是否在给定范围内。表格如下所示:

Key             Postalcode
---------------------------
1               58230
2               49034-9731
3               98801
4               M5H 4E7

我运行一个select语句

SELECT 
    key, CONVERT(int, LEFT(LTRIM(RTRIM(Postalcode)),5)) AS pcode 
FROM 
    Table 
WHERE
    LEFT(Postalcode, 5) NOT LIKE '%[^0-9]%'

,结果按预期返回表格。

Key             Postalcode
--------------------------
1               58230
2               49034
3               98801

然后我包装别名并尝试检查范围。

select 
    key, pcode 
from 
    (select 
         key, convert(int, LEFT(ltrim(rtrim(Postalcode)),5)) as pcode  
     from  
         Table 
     where 
         LEFT(Postalcode,5) not like '%[^0-9]%') x
 where 
     x.pcode between 58000 and 59000

SQL Server 2008返回此错误

  

Msg 245,Level 16,State 1,Line 1
  将varchar值'M5H 4'转换为数据类型int时,转换失败。

有人能告诉我发生了什么事吗?看起来像别名中的select正在对原始表进行一些扫描并遇到加拿大邮政编码。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果您想要pcode,请使用:

select key, pcode
from (select key,
             (case when postalcode like '[0-9][0-9][0-9][0-9][0-9]%'
                   then cast(left(postalcode, 5) as int)
              end) as pcode
      from t
     ) t
where t.pcode between 58000 and 59000;

但是,转换为int实际上是不必要的。你冷,只是使用:

select key, left(postalcode, 5)
from table t
where postalcode like '[0-9][0-9][0-9][0-9][0-9]%' and
      postalcode between '58000' and '59000';

将邮政编码视为字符串而不是数字更有意义。

而且,您的代码无法正常工作的原因是因为SQL Server不保证selectwhere中表达式的评估顺序。因此,它会在过滤之前将pcode的计算推送到。从性能角度来看,这是一件好事,但我认为这是一个错误。使用case(确保其条件的评估顺序)很容易解决。