我有一个表格,每个州的两个邮政编码之间有几行排列范围。我希望能够获取两个范围并在它们各自的行上显示两个范围之间的每个值。 EX下面。
Zip Start Zip End State
00501 06390 NY
10001 10314 NY
10451 11003 NY
我希望将数据显示为
00501 NY
00502 NY
00503 NY
00504 NY
非常感谢任何帮助。
DROP TABLE IF EXISTS yourTable;
CREATE TABLE yourTable as
Select '00501' as zipstart,'06390' as zipend,'NY' as state union
select'10001','10314','NY'union
select'10451','11003','NY'
Distributed by (ZipStart,ZipEnd,State);
WITH cte AS (
SELECT *
FROM
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n)
)
, cteTally AS (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as Num
FROM
cte c1
CROSS JOIN cte c2
CROSS JOIN cte c3
CROSS JOIN cte c4
CROSS JOIN cte c5
)
SELECT
SUBSTRING(ZipStart || CAST(tt.Num AS VARCHAR(100)),1,5) ZipSTart
,t.zipend,t.State
FROM
yourTable t
INNER JOIN cteTally tt
ON tt.Num <= CAST(t.ZipEnd AS INT)
AND tt.Num >= CAST(t.ZipStart AS INT)
答案 0 :(得分:3)
的PostgreSQL
select to_char(zip,'FM00000') as zip
,state
from t,generate_series("Zip Start"::int,"Zip End"::int) gs(zip)
;
答案 1 :(得分:1)
这是一个可以在PostgreSQL和其他几个平台上运行的Sql server版本。处理多达100,000个数字以进行扩展只需在cteTally定义中添加更多交叉连接。
IF OBJECT_ID('tempdb..#yourTable') IS NOT NULL
BEGIN
DROP TABLE #yourTable
END
CREATE TABLE #yourTable (ZipStart VARCHAR(5), ZipEnd VARCHAR(5), State CHAR(2));
INSERT INTO #yourTable VALUES
('00501','06390','NY')
,('10001','10314','NY')
,('10451','11003','NY');
WITH cte AS (
SELECT *
FROM
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n)
)
, cteTally AS (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as Num
FROM
cte c1 --10
CROSS JOIN cte c2 --100
CROSS JOIN cte c3 --1,000
CROSS JOIN cte c4 --10,000
CROSS JOIN cte c5 --100,000
)
SELECT
RIGHT('00000' || CAST(tt.Num AS VARCHAR(100)),5) as GeneratedZip
,t.ZipStart
,t.ZipEnd
,t.State
FROM
#yourTable t
INNER JOIN cteTally tt
ON tt.Num <= CAST(t.ZipEnd AS INT)
AND tt.Num >= CAST(t.ZipStart AS INT)
对于PostgreSQL以及支持generate_series
的平台,请查看Dudu's answer
答案 2 :(得分:1)
这适用于 Sql Server 。我把它留在这里只是因为我花时间写它。
使用数字表非常简单。
rextester:http://rextester.com/MEFE32862
来自@AaronBertrand's article on generating a set的号码表。
begin;
create table dbo.zip_ranges (id int ,StateName varchar(32) ,[State] char(2) ,Zip_Start int ,Zip_End int )
insert into dbo.zip_ranges (id, StateName, [State], Zip_Start, Zip_End) values
(1 ,'New York (Fishers Is)' ,'NY' ,501 ,6390) ,(2 ,'New York' ,'NY' ,10001 ,10314),(3 ,'New York' ,'NY' ,10001 ,10314) ,(4 ,'Ohio' ,'OH' ,43001 ,45999)
create unique clustered index n on dbo.zip_ranges(Id)
end;
/* 100,000 number table - stolen from @AaronBertrand https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1 */
begin;
select top (100000) n = convert(int, row_number() over (order by s1.[object_id]))
into dbo.numbers
from sys.all_objects as s1
cross join sys.all_objects as s2
option (maxdop 1);
create unique clustered index n on dbo.numbers(n)
end;
select
--Zip=n.n
--Zip=left('00000',5-len(n.n))+convert(varchar(5),n.n)
Zip=right('00000'+convert(varchar(5),n.n),5) /* grabbed this conversion from @Matt instead of my clunky one */
, z.[State]
from dbo.zip_ranges z
inner join dbo.numbers n on n >= z.zip_start and n <= z.zip_end
where z.[State]='NY'
order by n