SQL 滞后于前一个不同的值
SQL Lag distinct - to the previous different value
我将以下内容简化了很多列table。
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 按期间排序?
将#test 替换为您的 table 姓名。它只是 select,您可以将其更改为更新。请对此进行测试,因为您将遇到不同的情况。
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
您可以使用 window 函数执行此操作,但它比必要的更棘手,因为 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()
将先前的值分散到整个组中。
Here 是一个 db<>fiddle.
我将以下内容简化了很多列table。
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 按期间排序?
将#test 替换为您的 table 姓名。它只是 select,您可以将其更改为更新。请对此进行测试,因为您将遇到不同的情况。
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
您可以使用 window 函数执行此操作,但它比必要的更棘手,因为 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()
将先前的值分散到整个组中。
Here 是一个 db<>fiddle.