2011-07-22 5 views
3

У моего клиента есть регионы продаж, где каждый регион продаж состоит из списка почтовых индексов. регионов довольно большие и могут быть проще хранить в формате, как:Определите, являются ли несколько почтовых индексов смежными

Региона состоит из диапазона почтового индекса от 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 

Можно ли создать SearchableZip с SQL-скрипт?

EDIT

Я установил декларацию таблицы и выходные данные

+1

Операторы 'insert into Entered.ip ...' несовместимы. Они не соответствуют объявлению таблицы, а значения столбцов находятся в неправильном порядке. –

+0

Если у вас проблема с производительностью, это не способ ее решения. Измените свой вопрос и вставьте планы выполнения запросов для запросов, которые не работают хорошо. Как бы то ни было, похоже, что вы догадываетесь о решении. Угадание не очень хорошо масштабируется. –

+0

Вы правы в этом. Но я должен попробовать. Даже если это плохой способ (что это действительно возможно) –

ответ

7

Да, можно получить диапазоны из списка одним запросом. Для этого вы будете использовать CTE, ranking и немного 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 

Этот вывод не соответствует вашему, но это не соответствует данному источнику.


ОБНОВЛЕНИЕ

Если таблица Индекса является справочной таблицей для определения примыкания списка почтовых индексов, то указанный выше раствор должен быть изменен следующим образом:

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, потому что между этими двумя кодами нет другого почтового индекса, а затем 00601. Попробуйте сделать это сложнее, чем необходимо, указав неверные входные данные. –

+1

Я понимаю суть, хотя таблица Zip в вашем примере не содержит почтовый индекс '00601', который присутствует во введенном списке почтовых индексов. Возможно ли это в реальной ситуации или вы просто пропустили код по ошибке? –

+0

Хорошая точка: я исправил входные данные. –

0

во-первых, я должен сказать вам, что я думаю, что вы собираетесь делать, как мне кажется плохой идеей. Таблица EnteredZip отлично подходит для хранения области, к которой принадлежит почтовый индекс. (До тех пор, как вы поставите PRIMARY KEY ограничение на ZIP.)

Похоже, это примерно, где вы стремитесь,

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

но не совпадает с выходом. Честно говоря, ваш образец не имеет смысла для меня.

Существует только одна строка для Area1, но почтовые индексы не соприкасаются. Для Area2 есть две строки, но каждый имеет один ZIP-код. Для Area3 есть две строки, но ZIP-адреса не смежны.

Ждать. , ,

смежный означает, что вы вставили пустую строку между инструкциями INSERT в данных образца?

Если это так, то вам нужно хранить больше данных. Вы должны определить, какие почтовые индексы следует считать непрерывными, и хранить эти факты в таблице. (Также вы оставили пустую строку в Area2.)

+0

Я отредактировал образец вывода, чтобы его было легче читать. Я вижу, что вы делаете о том, что не являетесь хорошей идеей. Я просто хочу попробовать, если он решает мою проблему с производительностью. Возможно, у меня есть шанс, если регионы будут действительно большими. Индексы уже на месте, но этого недостаточно. –

Смежные вопросы