简体   繁体   English

SQL Server:如何为过去的交易分配正确的帐户?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM