从 100,101,102 等行创建范围(100-106、107、111-119)
Create ranges (100-106, 107, 111-119) from rows of 100,101,102, etc
我有一个 table 完整的美国所有邮政编码。
您可能知道邮政编码不一定是一个接一个,所以对于密歇根州,我有这些邮政编码(只是一个示例):
48001,48002,48003,48004,48005,48006,48007,48009,48012,48014,48015,48017
我需要做的是得到一行,例如:
48001-48007,48009,48012,48014-48015,48017
您可以看到我正在将顺序的邮政编码合并到开始-结束范围内,如果邮政编码不在一个序列中,它就会单独存在。
我只会处理一部分邮政编码,不会处理整个美国。因此,假设我有一个 temp table,其中包含我要使用的邮政编码,我可以根据需要填充此 temp table。现在这个临时 table 有一个邮政编码字段,但它可以根据需要定义。
我可以使用临时 tables、游标或其他任何东西,这将在存储过程中完成。如果您想知道为什么,我们有销售代表,每个人都负责特定的邮政编码,我们需要打印出某些代表。当客户服务接到客户的电话时,他们可以快速查看打印的 sheet 并扫描以查看负责该拉链的销售代表。
所以打印出来的纸看起来像:
Jim Smith...........48001-48007,48009,48012,48014-48015,48017
Heather Jones...59014, 59017, 59018-59022 (completely fake numbers, just as an example)
我意识到纸已经过时了,我们可以使用网站或任何其他方法来完成此操作,但无论出于何种原因必须打印它,所以我正在尝试尽可能地压缩邮政编码印刷用途。
您可以尝试以下方法。
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
您想将同一客户的相邻邮编组合在一起。我会将此作为差距和孤岛问题来解决,使用 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
customer_id | zip_range
----------: | :----------
1 | 48001-48007
1 | 48009
1 | 48012
1 | 48014-48015
1 | 48017
如果您有一列包含州和邮政编码,那么这是一个间隙和岛屿问题。对于各个范围:
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 hack 进行最终聚合。
我有一个 table 完整的美国所有邮政编码。 您可能知道邮政编码不一定是一个接一个,所以对于密歇根州,我有这些邮政编码(只是一个示例):
48001,48002,48003,48004,48005,48006,48007,48009,48012,48014,48015,48017
我需要做的是得到一行,例如:
48001-48007,48009,48012,48014-48015,48017
您可以看到我正在将顺序的邮政编码合并到开始-结束范围内,如果邮政编码不在一个序列中,它就会单独存在。
我只会处理一部分邮政编码,不会处理整个美国。因此,假设我有一个 temp table,其中包含我要使用的邮政编码,我可以根据需要填充此 temp table。现在这个临时 table 有一个邮政编码字段,但它可以根据需要定义。
我可以使用临时 tables、游标或其他任何东西,这将在存储过程中完成。如果您想知道为什么,我们有销售代表,每个人都负责特定的邮政编码,我们需要打印出某些代表。当客户服务接到客户的电话时,他们可以快速查看打印的 sheet 并扫描以查看负责该拉链的销售代表。
所以打印出来的纸看起来像:
Jim Smith...........48001-48007,48009,48012,48014-48015,48017
Heather Jones...59014, 59017, 59018-59022 (completely fake numbers, just as an example)
我意识到纸已经过时了,我们可以使用网站或任何其他方法来完成此操作,但无论出于何种原因必须打印它,所以我正在尝试尽可能地压缩邮政编码印刷用途。
您可以尝试以下方法。
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
您想将同一客户的相邻邮编组合在一起。我会将此作为差距和孤岛问题来解决,使用 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
customer_id | zip_range ----------: | :---------- 1 | 48001-48007 1 | 48009 1 | 48012 1 | 48014-48015 1 | 48017
如果您有一列包含州和邮政编码,那么这是一个间隙和岛屿问题。对于各个范围:
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 hack 进行最终聚合。