[英]SQL Server: How do I assign the correct account to past transactions?
SQL Gurus, I have a situation where I need to assign transactions to accounts where effective begin dates and effective end dates prior to 3/1/2017 exist in one table (#legacyt2), and anything past that date exists in the current dimension table (#type2). SQL Gurus,我遇到一种情况,我需要将交易分配给在一个表(#legacyt2)中存在有效开始日期和2017年3月1日之前的有效结束日期的帐户,而当前维度表中存在该日期之后的任何内容(#2型)。 I need to assign the correct skey (found in #type2 and #legacyt2) for the appropriate beg/end effective dates based on the transaction date found in the #fact table.
我需要根据#fact表中的交易日期为正确的开始/结束有效日期分配正确的密钥(在#type2和#legacyt2中找到)。
I've come close, but I haven't been able to assign the accounts correctly. 我已经接近了,但是我无法正确分配帐户。 I've provided the build script and the queries that work.
我提供了构建脚本和有效的查询。
The end result that I am looking for based on the script provided is this: 根据所提供的脚本,我正在寻找的最终结果是:
drop table #type2;
create table #type2
(ckey int,
skey int,
lastUpdated date,
begdate date,
enddate date
);
insert into #type2
(ckey,skey,lastupdated,begdate,enddate)
values
(1,100,'9/26/2017','5/9/2017','5/11/2017');
insert into #type2
(ckey,skey,lastupdated,begdate)
values
(1,125,'9/26/2017','5/11/2017');
drop table #legacyt2;
create table #legacyt2
(ckey int,
skey int,
lastUpdated date,
begdate date,
enddate date
);
insert into #legacyt2
(ckey,skey,lastupdated,begdate,enddate)
values
(1,100,'3/1/2017','1/22/2016','2/5/2017');
insert into #legacyt2
(ckey,skey,lastupdated,begdate)
values
(1,125,'3/1/2017','2/5/2017');
drop table #fact;
create table #fact
(ckey int,
xactDate date,
acct int,
amt decimal(10,2)
);
insert into #fact
(ckey,xactDate,acct,amt)
values
(1,'1/24/2017',1,10.00);
insert into #fact
(ckey,xactDate,acct,amt)
values
(1,'1/24/2017',10,10.00);
insert into #fact
(ckey,xactDate,acct,amt)
values
(1,'1/30/2017',1,20.00);
insert into #fact
(ckey,xactDate,acct,amt)
values
(1,'2/2/2017',1,80.00);
insert into #fact
(ckey,xactDate,acct,amt)
values
(1,'2/3/2017',10,20.00);
insert into #fact
(ckey,xactDate,acct,amt)
values
(1,'2/6/2017',1,50.00);
select ckey,
skey,
lastupdated,
begdate,
enddate
from #type2
-- Step #1: collect legacy and current dimension type 2 info and rank to identify current and previous versions.
select ckey,
skey,
lastupdated,
begdate,
enddate
from #legacyt2
drop table #dim;
with Dimension as
( select t2.ckey,
t2.skey,
t2.begdate,
l2.begdate as LegacyBegDate,
t2.enddate,
l2.enddate as LegacyEndDate,
row_number() over (partition by t2.ckey order by max(t2.begdate)) as rnk
from #type2 t2
left join #legacyt2 l2
on l2.ckey = t2.ckey
and l2.skey = t2.skey
group by t2.ckey,t2.skey,t2.begdate,t2.enddate,l2.begdate,l2.enddate
)
select ckey,
skey,
begdate,
legacyBegDate,
enddate,
legacyenddate,
rnk
into #dim
from Dimension
order by ckey,begdate;
select * from #dim
I think I understood you. 我想我了解你。 Try it:
试试吧:
;WITH dimension
AS (SELECT ckey
,skey
,begdate xactDate
FROM #type2
UNION
SELECT ckey
,skey
,enddate xactDate
FROM #type2
WHERE enddate IS NOT NULL
UNION
SELECT ckey
,skey
,begdate xactDate
FROM #legacyt2
UNION
SELECT ckey
,skey
,enddate xactDate
FROM #legacyt2
WHERE enddate IS NOT NULL),
dimension2
AS (SELECT Row_number()
OVER (
partition BY ckey
ORDER BY skey, xactdate) rn
,ckey
,skey
,xactdate
FROM dimension),
fact1
AS (SELECT Row_number()
OVER (
partition BY ckey
ORDER BY xactdate) rn
,ckey
,xactdate
,acct
,amt
FROM #fact)
SELECT A.ckey
,b.skey
,a.xactdate
,a.acct
,a.amt
INTO #dim
FROM fact1 a
INNER JOIN dimension2 b
ON a.ckey = b.ckey
AND a.rn = b.rn
ORDER BY a.ckey
,A.rn
SELECT *
FROM #dim
Result 结果
ckey skey xactDate acct amt
----------- ----------- ---------- ----------- ---------------------------------------
1 100 2017-01-24 1 10.00
1 100 2017-01-24 10 10.00
1 100 2017-01-30 1 20.00
1 100 2017-02-02 1 80.00
1 125 2017-02-03 10 20.00
1 125 2017-02-06 1 50.00
Although @Mauricio Pontalti Neri did a super job, in the end, the simplest and clearest way to move forward with solving for this problem was to work with the #fact staging table by adding a new column for skey for updates and utilizing the #dim. 尽管@Mauricio Pontalti Neri做了出色的工作,但最终,解决此问题的最简单,最清晰的方法是使用#fact临时表,方法是添加一个新的skey列以进行更新并利用#dim 。 This won't win any awards for eloquence, but it does get the job done.
这不会赢得任何口才奖,但确实可以完成工作。
Here's what the solution looks like: 解决方案如下所示:
-- step #1 dump the legacy/current dimension information into a combined #temp table.
with Dimension as
( select t2.ckey,
t2.skey,
t2.begdate,
l2.begdate as LegacyBegDate,
t2.enddate,
l2.enddate as LegacyEndDate,
row_number() over (partition by t2.ckey order by max(t2.begdate)) as rnk
from #type2 t2
left join #legacyt2 l2
on l2.ckey = t2.ckey
and l2.skey = t2.skey
group by t2.ckey,t2.skey,t2.begdate,t2.enddate,l2.begdate,l2.enddate
)
select ckey,
skey,
begdate,
legacyBegDate,
enddate,
legacyenddate,
rnk
into #dim
from Dimension
order by ckey,begdate;
-- step #2 update the skey for current ckey/skey pairings.
update #fact
set #fact.skey = x.skey
from (select skey,
ckey,
LegacyBegDate,
LegacyEndDate,
begdate,
enddate
from #dim
where enddate is null
and legacyenddate is null
)x
where #fact.ckey = x.ckey
and #fact.xactdate between cast(x.legacyBegDate as date) and cast(getdate() as date)
-- step #3 update the skey for closed ckey/skey pairings.
update #fact
set #fact.skey = x.skey
from (select skey,
ckey,
LegacyBegDate,
LegacyEndDate,
begdate,
enddate
from #dim
where enddate is NOT null
and legacyenddate is NOT null
)x
where #fact.ckey = x.ckey
and #fact.xactdate between cast(x.legacyBegDate as date) and cast(x.legacyEndDate as date)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.