2011-07-22 9 views
3

私の顧客には、各販売地域が郵便番号のリストで構成されている販売地域があります。 領域はかなり大きいですし、同じように簡単なフォーマットで保存することができますいくつかの郵便番号が連続しているかどうかを確認

地域は10012から00602と20020から私はに郵便番号のリストから取得できますか30020

に郵便番号の範囲で構成されていそのような郵便番号の範囲のリスト?

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

SearchableZip

--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') 

は、テーブル内のこのエントリにつながる次のデータを考慮して、それには、SQLスクリプトでSearchableZipを作成することは可能ですか?私はまず

+1

'into into EnteredZip ...'文は矛盾しています。それらはテーブルの宣言と一致せず、列の値の順序が間違っています。 –

+0

パフォーマンスの問題がある場合は、これを解決する方法ではありません。質問を編集し、うまく機能しないクエリのクエリ実行計画を貼り付けます。それが立てば、ソリューションを推測しているように見えます。推測はうまくスケールされません。 –

+0

あなたはそれについて正しいです。しかし、私はそれを試しなければなりません。それが悪い方法であっても(実際にはそうかもしれませんが) –

答えて

7

はい、1つのクエリで範囲から範囲を取得することは可能です(例:Area2に空白行を入れなかった場合)。そのために、あなたは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 

は、この出力はあなたのものと一致していないが、それは元のデータと一致しません。


UPDATE

ジップテーブルは郵便番号のリストの連続性を判定するための参照テーブルである場合、上記の溶液は次のように修正されるべきである:

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 
+0

サンプルデータの出力が正しくなりました。テーブルZipが必要であるため、あなたが与えたクエリは機能しません。たとえば、Area1にはStartZip 00544とEndzip 00602があります。これら2つのコードの間に他の郵便番号は存在しません。したがって、間違った入力データを与えることでこれをもっと困難にするために。 –

+1

サンプルのZipテーブルには、入力された郵便番号リストに存在する '00601'郵便番号が含まれていませんが、その点を理解しています。これは現実の状況で可能ですか、間違ってコードを省略しましたか? –

+0

良い点:入力データを修正しました。 –

0

テーブル宣言と出力データを固定

EDIT

、私は私があなたがすることを計画している考えるは悪いアイデアとして私を打つことを伝える必要があります。 EnteredZipテーブルは、郵便番号がどのエリアに属しているかを保存するのに便利です。 (限り、あなたはZIPにPRIMARY KEY制約を置くよう。)

それは、あなたが目指しているところ、これはおおよそであるよう

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

に見えるが、それはあなたの出力と一致していません。率直に言って、あなたのサンプル出力は私には意味がありません。

Area1には1行しかありませんが、郵便番号は連続していません。 Area2には2つの行がありますが、それぞれに1つのZIPコードがあります。 Area3には2つの行がありますが、ZIPは連続していません。

待機。 。 。

が連続していますは、サンプルデータのINSERT文の間に空白行を挿入したことを意味しますか?

この場合、より多くのデータを保存する必要があります。どのZIPコードを連続したものにするかを特定し、それらの事実をテーブルに格納する必要があります。

+0

サンプルの出力を読みやすく編集しました。良いアイデアではない点を見ています。私のパフォーマンスの問題を解決したいのですが。地域が本当に大きければチャンスがあるかもしれません。インデックスはすでに整っていますが、十分ではありませんでした。 –