SQL 函数到 运行 一个在标志改变时增加的计数器?
SQL function to run a counter that increases when a flag changes?
我有看起来像前三列的数据,我想为 Cycle 添加第四列,当 Flag 为零时它为空,否则计算给定 x 的该标志的出现次数, 按日期排序。我正在使用 db2,但不确定如何修改 row_number() 函数来获得此结果。
name date Flag Cycle
x 2014 0 Null
x 2015 0 Null
x 2016 1 1
x 2017 1 1
x 2018 0 Null
x 2019 1 2
x 2020 0 Null
x 2021 1 3
y 2014 0 Null
y 2016 1 1
y 2017 0 Null
y 2018 1 2
我正在寻找行为类似于 Rank 函数的东西,但允许基于分区语句中的重复项而不是排序依据进行并列排名。
您可以使用 lag()
和 window sum()
:
select
name,
date,
flag,
case when flag = 1
then sum(cycle_start) over(partition by name order by date)
end cycle
from (
select
t.*,
case
when lag(flag) over(partition by name order by date) = 0 and flag = 1
then 1
end cycle_start
from mytable t
) t
order by name, date
内部查询检测到循环开始是从 0
到 1
的过渡。外部查询对循环开始进行 window 求和,并仅在标志打开时显示它。
NAME | DATE | FLAG | CYCLE
---: | ---: | ---: | ----:
x | 2014 | 0 | null
x | 2015 | 0 | null
x | 2016 | 1 | 1
x | 2017 | 1 | 1
x | 2018 | 0 | null
x | 2019 | 1 | 2
x | 2020 | 0 | null
x | 2021 | 1 | 3
y | 2014 | 0 | null
y | 2016 | 1 | 1
y | 2017 | 0 | null
y | 2018 | 1 | 2
好像是一个累计数:
select t.*,
(case when flag = 1
then sum(flag) over (partition by name order by date)
end) as cycle_start
from t;
这假设标志仅采用值 0
和 1
,如示例数据中所示。如果标志采用其他非 0
值,则可以轻松修改它。
编辑:
根据您的评论,我误解了问题。您想要识别相邻的 "groups" 条记录。为此,使用先前 NULL
值的数量定义一个组,然后进行累加和:
select t.*,
(case when flag = 1
then dense_rank() over (partition by name order by grp)
end) as cycle_start
from (select t.*,
sum(1 - flag) over (partition by name order by date) as grp
from t
) t
我有看起来像前三列的数据,我想为 Cycle 添加第四列,当 Flag 为零时它为空,否则计算给定 x 的该标志的出现次数, 按日期排序。我正在使用 db2,但不确定如何修改 row_number() 函数来获得此结果。
name date Flag Cycle
x 2014 0 Null
x 2015 0 Null
x 2016 1 1
x 2017 1 1
x 2018 0 Null
x 2019 1 2
x 2020 0 Null
x 2021 1 3
y 2014 0 Null
y 2016 1 1
y 2017 0 Null
y 2018 1 2
我正在寻找行为类似于 Rank 函数的东西,但允许基于分区语句中的重复项而不是排序依据进行并列排名。
您可以使用 lag()
和 window sum()
:
select
name,
date,
flag,
case when flag = 1
then sum(cycle_start) over(partition by name order by date)
end cycle
from (
select
t.*,
case
when lag(flag) over(partition by name order by date) = 0 and flag = 1
then 1
end cycle_start
from mytable t
) t
order by name, date
内部查询检测到循环开始是从 0
到 1
的过渡。外部查询对循环开始进行 window 求和,并仅在标志打开时显示它。
NAME | DATE | FLAG | CYCLE ---: | ---: | ---: | ----: x | 2014 | 0 | null x | 2015 | 0 | null x | 2016 | 1 | 1 x | 2017 | 1 | 1 x | 2018 | 0 | null x | 2019 | 1 | 2 x | 2020 | 0 | null x | 2021 | 1 | 3 y | 2014 | 0 | null y | 2016 | 1 | 1 y | 2017 | 0 | null y | 2018 | 1 | 2
好像是一个累计数:
select t.*,
(case when flag = 1
then sum(flag) over (partition by name order by date)
end) as cycle_start
from t;
这假设标志仅采用值 0
和 1
,如示例数据中所示。如果标志采用其他非 0
值,则可以轻松修改它。
编辑:
根据您的评论,我误解了问题。您想要识别相邻的 "groups" 条记录。为此,使用先前 NULL
值的数量定义一个组,然后进行累加和:
select t.*,
(case when flag = 1
then dense_rank() over (partition by name order by grp)
end) as cycle_start
from (select t.*,
sum(1 - flag) over (partition by name order by date) as grp
from t
) t