【问题标题】:SQL function to run a counter that increases when a flag changes?SQL函数运行一个在标志改变时增加的计数器?
【发布时间】:2020-01-13 20:04:00
【问题描述】:

我有看起来像前三列的数据,我想为 Cycle 添加第四列,当标志为零时为空,否则计算给定 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 函数的东西,但允许基于分区语句中的重复项而不是 order by 进行并列排名。

【问题讨论】:

    标签: sql db2 counter window-functions cycle


    【解决方案1】:

    看起来像一个累积和:

    select t.*,
           (case when flag = 1
                 then sum(flag) over (partition by name order by date)
            end) as cycle_start
    from t;
    

    这假定标志仅采用值01,如示例数据中所示。如果标志采用其他非0 值,则可以轻松修改它。

    编辑:

    根据您的评论,我误解了这个问题。您想要识别相邻的记录“组”。为此,使用先前的 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
    

    【讨论】:

    • 打算提出相同的方法,你(一如既往)击败了我。
    • 感谢您的建议,但这并不是我想要的!我正在寻找一种解决方案,可以将具有相同标志的行分配给同一个循环。
    • @Ara 。 . .我误解了。我用替代版本更新了答案。
    【解决方案2】:

    你可以使用lag()和一个窗口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
    

    内部查询将循环开始检测为从01 的转换。外部查询执行循环开始的窗口总和,并仅在标志打开时显示。

    Demo on DB Fiddlde

    姓名 |日期 |旗帜 |循环 ---: | ---: | ---: | ----: x | 2014 | 0 | x | 2015 | 0 | x | 2016 | 1 | 1 x | 2017 | 1 | 1 x | 2018 | 0 | x | 2019 | 1 | 2 x | 2020 | 0 | x | 2021 | 1 | 3 是 | 2014 | 0 | 是 | 2016 | 1 | 1 是 | 2017 | 0 | 是 | 2018 | 1 | 2

    【讨论】:

    • 这让我更接近我想要的位置,但我希望将 Y 的 2016 年设置为周期 1,因为它之前的标志也是 1。目前它设置为 null .
    • @Ara:这是查询中的一个微小变化(您的示例数据也发生了变化)。固定!
    • 正是我想要的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 2020-06-24
    • 2021-12-13
    • 1970-01-01
    相关资源
    最近更新 更多