Создайте диапазоны (100-106, 107, 111-119) из строк 100, 101, 102 и т. Д. - PullRequest
3 голосов
/ 29 января 2020

У меня есть таблица, полная всех почтовых индексов в США. Как вы, наверное, знаете, почтовые индексы не обязательно являются друг за другом, поэтому для Мичигана у меня есть следующие почтовые индексы (просто пример):

48001,48002,48003,48004,48005,48006,48007,48009,48012,48014,48015,48017

Что мне нужно сделать, так это получить одну строку, такую ​​как :

48001-48007,48009,48012,48014-48015,48017

Вы можете видеть, что я объединяю почтовые индексы, которые являются последовательными, в начальный и конечный диапазон, и если почтовый индекс не входит в последовательность, он будет сам по себе.

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

Я могу использовать временные таблицы, курсоры или что-нибудь еще, это будет сделано в сохраненном процедура. В случае, если вам интересно, почему, у нас есть торговые представители, и каждый отвечает за указание c почтовых индексов, и нам нужно распечатать некоторых представителей. Когда клиент получает звонок от клиента, он может быстро просмотреть распечатанный лист и отсканировать, чтобы увидеть торгового представителя, который будет отвечать за этот почтовый индекс.

Таким образом, напечатанная бумага будет выглядеть следующим образом:

Jim Smith...........48001-48007,48009,48012,48014-48015,48017
Heather Jones...59014, 59017, 59018-59022  (completely fake numbers, just as an example)

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

Ответы [ 3 ]

1 голос
/ 29 января 2020

Вы хотите сгруппировать смежные почтовые индексы одного и того же клиента. Я бы рассмотрел это как проблему пробелов и островков, используя lag() и совокупный sum() для определения групп:

select 
    customer_id,
    case when min(zip) = max(zip) 
        then concat(min(zip), '')
        else concat(min(zip),  '-', max(zip))
    end zip_range
from (
    select 
        customer_id,
        zip,
        sum(case when zip = lag_zip + 1 then 0 else 1 end) 
            over(partition by customer_id order by zip) grp
    from (
        select
            customer_id,
            zip,
            lag(zip) over(partition by customer_id order by zip) lag_zip
        from mytable t
    ) t
) t
group by customer_id, grp

Демонстрация на DB Fiddle :

customer_id | zip_range  
----------: | :----------
          1 | 48001-48007
          1 | 48009      
          1 | 48012      
          1 | 48014-48015
          1 | 48017      
1 голос
/ 29 января 2020

Вы можете попробовать следующее.

create table zipcodes(zcode int);

insert into zipcodes
 select *
   from (values(48001),(48002),(48003),(48004),(48005),(48006),(48007),(48009),(48012),(48014),(48015),(48017))t(x);


select case when count(*) >1 then 
             concat(min(zcode),'-',max(zcode)) 
            else concat(max(zcode),'')
        end as concat_zcodes
from (
        select zcode
               ,ROW_NUMBER() over(order by zcode asc)  as rnk
               ,zcode - ROW_NUMBER() over(order by zcode asc) as grp
          from zipcodes
     )x
group by x.grp
0 голосов
/ 29 января 2020

Если у вас есть столбец с состоянием и почтовым индексом, то это проблема пробелов и островов. Для отдельных диапазонов:

select state,
       (case when min(zip_code) = max(zip_code)
             then min(zip_code)
             else concat(min(zip_code), '-', max(zip_code)
        end) as zips
from (select t.*,
             convert(int, zip_code) - row_number() over (partition by state order by zip_code) as grp
      from t
     ) t
group by state, grp;

Для вашего окончательного результата снова агрегируйте:

select state, string_agg(zip_code, ',') 
from (select state,
             (case when min(zip_code) = max(zip_code)
                   then min(zip_code)
                   else concat(min(zip_code), '-', max(zip_code)
              end) as zips
      from (select t.*,
                   convert(int, zip_code) - row_number() over (partition by state order by zip_code) as grp
            from t
           ) t
      group by state, grp
     ) sg
group by state;

В более старых версиях вам потребуется использовать хак XML для окончательного агрегирования .

...