我每个月都会得到一份用户列表及其家庭邮政编码。但是,并非每个用户都提供每个月的邮政编码,因此我的月度表大小永远都不会相同。
我要做的是创建一个主表,该表具有从第一个月开始的每个用户每个月的记录。然后,如果第一个月的用户没有出现在第二个月,则他们仍应获得第二个月的记录,并根据上个月分配邮政编码。
例如,我有两个看起来像这样的表:
UserNumber Month ZIP
1 201701 12345
2 201701 30032
3 201701 01432
Etc.
UserNumber Month ZIP
1 201702 12345
3 201702 01433
4 201702 30032
Etc.
您可以看到一些邮政编码会更改(用户3被“移动”),这没关系。但是用户2没有201702的记录。但是我的新主表应该为他们使用201701邮政编码的记录。因此,主表应如下所示:
UserNumber Month ZIP
1 201701 12345
1 201702 12345
2 201701 30032
2 201702 30032
3 201701 01432
Etc.
如上所述,用户2的201702记录使用与我们有记录相同的邮政编码。有时会丢失多个月份,所以我想获取比当前月份少的最新记录。
我曾尝试基于表相交创建多个临时表,然后将它们附加在一起,并且有效。但是,随着30个月以上的数据变得非常复杂和乏味,因此我希望有更好的方法。而且该主表也必须每个月进行更新。
任何建议,我将不胜感激!
当前数据位于S3中,我可以使用Hive进行访问,因此HiveQL解决方案将是理想选择,因此我不必将所有数据导入到SSMS中,但是如果使用SQL在SSMS中这样做更容易,我可以做到这一点也是
答案 0 :(得分:1)
以下解决方案适合您的问题:
begin tran
create table #tbl1 (UserNumber int, [Month] int, ZIP char(5));
create table #tbl2 (UserNumber int, [Month] int, ZIP char(5));
create table #tbl3 (UserNumber int, [Month] int, ZIP char(5));
insert into #tbl1 (UserNumber, [Month], ZIP)
select 1, 201701, '12345' union all
select 2, 201701, '30032' union all
select 3, 201701, '01432';
insert into #tbl2 (UserNumber, [Month], ZIP)
select 1, 201702, '12345' union all
select 3, 201702, '01433' union all
select 4, 201702, '30032';
insert into #tbl3 (UserNumber, [Month], ZIP)
select 3, 201703, '01435' union all
select 4, 201703, '30032';
create table #full (UserNumber int, [Month] int, ZIP char(5));
insert into #full (UserNumber, [Month], ZIP)
select UserNumber, [Month], ZIP from #tbl1
union all
select UserNumber, [Month], ZIP from #tbl2
union all
select UserNumber, [Month], ZIP from #tbl3;
CREATE UNIQUE CLUSTERED INDEX [CI_Full] ON #full (UserNumber asc, [Month] asc);
create table #month ([Month] int);
insert into #month ([Month])
select [Month]
from #full
group by [Month];
CREATE UNIQUE CLUSTERED INDEX [CI_Month] ON #month ([Month] asc);
create table #start_usernumber (UserNumber int, [Month] int);
insert into #start_usernumber (UserNumber, [Month])
select UserNumber, min([Month])
from #full
group by UserNumber;
CREATE UNIQUE CLUSTERED INDEX [CI_StartUserNumber] ON #start_usernumber (UserNumber asc, [Month] asc);
select su.UserNumber,
m.[Month],
case when(f.ZIP is null) then (select top(1) f0.ZIP from #full as f0 where f0.UserNumber=su.UserNumber and f0.[Month]<m.[Month] and f0.ZIP is not null order by f0.[Month] desc) else f.ZIP end as ZIP
from #start_usernumber as su
inner join #month as m on su.[Month]<=m.[Month]
left join #full as f on m.[Month]=f.[Month] and su.UserNumber=f.UserNumber
order by su.UserNumber, m.[Month];
rollback tran
结果:
答案 1 :(得分:1)
至少在您构建完初始集之后,听起来像这样的事情就会起作用。这确实是假设该过程每个月都进行更新,以使该系列中不会出现空白:
EditInput
如果要填补空白,可以从一个空表开始,然后循环运行30多次。如果表名是可预测的,则类似这样的内容可能会生成整个脚本。
insert into Master (userid, month, zip)
select
coalesce(u.userid, m.userid),
coalesce(u.month, convert(char(6), dateadd(month, 1, m.month + '01'), 112),
coalesce(u.zip, m.zip)
from ZipUpdate u full outer join Master m
on m.userid = u.userid and m.month =
convert(char(6), dateadd(month, -1, u.month + '01'), 112);