确定一些邮政编码是否连续

时间:2011-07-22 22:21:42

标签: sql-server sql-server-2008

我的客户拥有销售区域,其中每个销售区域都包含一个邮政编码列表。 这些区域非常大,可以更容易地存储,如:

区域由邮政编码组成,范围从00602到10012和20020到30020.

如何从邮政编码列表中获取此类邮政编码范围列表?

请考虑以下数据

--This would be my list of all available zip codes in us:

CREATE TABLE [Zip](
    [Zip] [nvarchar](20) ,
    [State] [nvarchar](50) ,
)

--This would be the Sales Region List

CREATE TABLE [dbo].[SalesRegion](
    [AreaCode] [nvarchar](50) 
) 

--This would be the original large list Zip Codes for the SalesRegions

CREATE TABLE [dbo].[EnteredZip](
    [Zip] [nvarchar](20) ,
    [AreaCode] [nvarchar](50) 
) 

--This is where I would like to store the Zip Code Ranges

CREATE TABLE [dbo].[SearchableZip](
    [StartZip] [nvarchar](20) ,
    [EndZip] [nvarchar](20) ,
    [AreaCode] [nvarchar](50) 
) 

--Here is my sample Data:

--Some Zip Codes in US
insert into dbo.Zip (Zip,[State]) values ('00501'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00544'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00601'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00602'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00603'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00604'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00605'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00606'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00610'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00611'   ,'PR')
insert into dbo.Zip (Zip,[State]) values ('00612'   ,'PR')


--Some Sales Regions

Insert Into dbo.SalesRegion ( AreaCode ) values('Area1')
Insert Into dbo.SalesRegion ( AreaCode ) values('Area2')
Insert Into dbo.SalesRegion ( AreaCode ) values('Area3')


--The zip codes of the Sales Regions
insert Into EnteredZip (Zip,AreaCode) values ('00544' , 'Area1')
insert Into EnteredZip (Zip,AreaCode) values ('00601' , 'Area1')
insert Into EnteredZip (Zip,AreaCode) values ('00602' , 'Area1')

insert Into EnteredZip (Zip,AreaCode) values ('00604' , 'Area2')
insert Into EnteredZip (Zip,AreaCode) values ('00606' , 'Area2')

insert Into EnteredZip (Zip,AreaCode) values ('00501' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00544' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00601' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00602' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00603' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00604' , 'Area3')

insert Into EnteredZip (Zip,AreaCode) values ('00610' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00611' , 'Area3')
insert Into EnteredZip (Zip,AreaCode) values ('00612' , 'Area3')

会在表SearchableZip

中产生这些条目
AreaCode             StartZip             EndZip
-------------------- -------------------- -------------------------
Area1                00544                00602
Area2                00604                00604
Area2                00606                00606
Area3                00501                00604
Area3                00610                00612

是否可以使用sql脚本创建SearchableZip?

修改

我修复了表声明和输出数据

2 个答案:

答案 0 :(得分:7)

是的,可以通过单个查询从列表中获取范围。为此,您将使用CTEranking和一点grey matter

WITH ranked AS (
  SELECT
    Zip,
    AreaCode,
    ZipGroup = CAST(Zip AS int)
             - ROW_NUMBER() OVER (PARTITION BY AreaCode ORDER BY Zip)
  FROM EnteredZip
)
SELECT
  StartZip = MIN(Zip),
  EndZip   = MAX(Zip),
  AreaCode
FROM ranked
GROUP BY AreaCode, ZipGroup

输出:

StartZip             EndZip               AreaCode
-------------------- -------------------- -------------------------
00544                00544                Area1
00601                00602                Area1
00604                00604                Area2
00606                00606                Area2
00501                00501                Area3
00544                00544                Area3
00601                00604                Area3
00610                00612                Area3

此输出与您的输出不匹配,但它与源数据匹配。


<强>更新

如果Zip表是用于确定邮政编码列表的连续性的参考表,那么上述解决方案应该像这样修改:

WITH ZipRanked AS (
  SELECT
    Zip,
    State,
    ZipRank = ROW_NUMBER() OVER (PARTITION BY State ORDER BY Zip)
  FROM Zip
),
EnteredZipRanked AS (
  SELECT
    e.Zip,
    e.AreaCode,
    ZipGroup = z.ZipRank
             - ROW_NUMBER() OVER (PARTITION BY e.AreaCode ORDER BY e.Zip)
  FROM EnteredZip e
    INNER JOIN ZipRanked z ON e.Zip = z.Zip
)
SELECT
  StartZip = MIN(Zip),
  EndZip   = MAX(Zip),
  AreaCode
FROM EnteredZipRanked
GROUP BY AreaCode, ZipGroup

答案 1 :(得分:0)

首先,我需要告诉你,我想要做的事情你打算做的事情让我感到沮丧。 EnteredZip表适用于存储邮政编码所属的区域。 (只要在ZIP上放置PRIMARY KEY约束。)

看起来这大致是你瞄准的地方,

select areacode, min(zip), max(zip)
from enteredzip
group by areacode
order by areacode

但它与您的输出不匹配。坦率地说,你的样本输出对我没有意义。

Area1只有一行,但邮政编码不是连续的。 Area2有两行,但每行都有一个邮政编码。 Area3有两行,但ZIP不是连续的。

等等。 。

连续是否意味着您在示例数据中的INSERT语句之间插入了一个空行?

如果是这种情况,那么您需要存储更多数据。您必须确定哪些邮政编码应被视为连续,并将这些事实存储在表格中。 (另外,你在Area2中省略了一个空行。)