1

我通过许多列表简化了以下内容。

 Person     Period           Cost_Center Previous_Cost_Center
----------- ---------------- ----------- ----------------------
123         2019003          1            
123         2019004          1            
123         2019005          2            
123         2019006          2            
123         2019007          3            

对于每个人,我想找到他以前的成本中心并将其保存在相应的列中。以前的成本中心必须与当前的不同。

我想得到什么:

Person      Period           Cost_Center Previous_Cost_Center
----------- ---------------- ----------- ---------------------
123         2019003          1           NULL 
123         2019004          1           NULL 
123         2019005          2           1 
123         2019006          2           1                     <----- Problematic row 
123         2019007          3           2 

在此期间的标准 LAG() 函数实际上会输出:

Person      Period           Cost_Center Previous_Cost_Center
----------- ---------------- ----------- ---------------------
123         2019003          1           NULL 
123         2019004          1           NULL 
123         2019005          2           1 
123         2019006          2           2                     <----- Problematic row 
123         2019007          3           2 

我想在有问题的行中是最后一个不同的 Cost_Center 值,它是 1 而不是 2。我想使用的是检查以前的 Cost_Center 是否不同:

          CASE
                WHEN
                    LAG ( Cost_Center ) OVER ( PARTITION BY Person ORDER BY Period ) != Cost_Center
                THEN
                    LAG ( Cost_Center ) OVER ( PARTITION BY Person ORDER BY Period )
                ELSE
                    Previous_Cost_Center
                END
            AS Previous_Cost_Center,

但后来我最终在第 4 行中根本没有 Previous_Cost_Center 值。如何使用 SQL 归档?如何接管最后一个不同的 Cost_Center 值以将其保存在按期间排序的 Previous_Cost_Center 中?

4

2 回答 2

1

将#test 替换为您的表名。它只是选择,您可以将其更改为更新。请对此进行测试,因为您将遇到不同的情况。

SELECT s.person,
       s.period,
       s.cost_center,
       CASE WHEN z.person IS NULL THEN NULL ELSE z.cc END AS Previous_Cost_Center
FROM   #test s
       LEFT JOIN (SELECT *
                  FROM   (SELECT t1.*,
                                 t2.cost_center               cc,
                                 Row_number()OVER (partition BY t2.person, t1.period ORDER BY t2.period DESC) RN
                          FROM   #test t1
                                 JOIN #test t2
                                   ON t1.person = t2.person
                                      AND t1.period > t2.period
                          WHERE  t1.cost_center <> t2.cost_center)s
                  WHERE  rn = 1
         )z
              ON s.person = z.person
                 AND s.period = z.period 
于 2021-04-13T08:38:57.533 回答
1

ignore null您可以使用窗口函数来执行此操作,但由于s 选项不可用,因此它比必要的更棘手。

首先,您希望将分组分配给同一组的相邻值。

其次,您希望将分组中的第一个值赋予上一个成本中心。

第三,你想在整个团队中“传播”这个价值。

select t.*,
       max(case when immediate_prev_cost_center <> cost_center then immediate_prev_cost_center
           end) over (partition by person, cost_center, (seqnum - seqnum_2)
                     ) as prev_cost_center
  from (select t.*,
               row_number() over (partition by person order by period) as seqnum,
               row_number() over (partition by person, cost_center order by period) as seqnum_2,
               lag(cost_center) over (partition by person order by period) as immediate_prev_cost_center
        from t
       ) t;

行号的差异定义了组。将max()先前的值传播到整个组中。

是一个 db<>fiddle。

于 2021-04-13T11:47:10.743 回答