【问题标题】:Get the no of consecutive days a Field value is Stale获取字段值过时的连续天数
【发布时间】:2020-06-11 08:34:01
【问题描述】:

我想根据费率表获取某个字段值过时的连续记录数。 从下面的数据记录中,3,4,5 的比率与 0.770827 相同,因此过时的天数是 3,过时之前的前一个比率是 0.770886。我想在编写对记录数的查询时得到帮助具有陈旧汇率并且也达到相同汇率的先前汇率。在下面的示例中,我仅显示加元兑美元,但我们需要不同货币的相同汇率。 任何帮助都会非常有帮助。

预期输出

【问题讨论】:

    标签: sql oracle group-by window-functions gaps-and-islands


    【解决方案1】:

    这是一个空白和孤岛问题。

    您可以使用lag() 检索相同货币元组的先前rate,然后进行窗口求和以定义具有相同汇率的连续记录组。然后,您可以聚合这些组,并再次使用lag() 恢复之前的速率。最后一步是筛选至少有 3 条记录的组。

    select *
    from (
        select
            from_cur,
            to_cur,
            rate,
            max(date) max_date,
            lag(rate) over(partition by from_cur, to_cur order by max(date)) lag_rate_grp,
            count(*) cnt
        from (
            select
                t.*,
                sum(case when rate = lag_rate then 0 else 1 end) over(partition by from_date, to_date order by date) grp 
            from (
                select 
                    t.*,
                    lag(rate) over(partition by from_cur, to_cur order by date) lag_rate
                from mytable t
            ) t
        ) t
        group by from_cur, to_cur, rate, grp
    ) t
    where cnt >= 3
    order by from_cur, to_cur, max_date
    

    其实利用行号的差异可以省去一层嵌套:

    select *
    from (
        select
            from_cur,
            to_cur,
            rate,
            max(date) max_date,
            lag(rate) over(partition by from_cur, to_cur order by max(date)) lag_rate_grp,
            count(*) cnt
        from (
            select
                t.*,
                row_number() over(partition by from_cur, to_cur order by date) rn1,
                row_number() over(partition by from_cur, to_cur, rate order by date) rn2         
            from mytable t
        ) t
        group by from_cur, to_cur, rate, rn1 - rn2
    ) t
    where cnt >= 3
    order by from_cur, to_cur, max_date
    

    如果您只想要每个货币元组的最早记录,那么您可以使用row_number()

    select *
    from (
        select
            from_cur,
            to_cur,
            rate,
            max(date) max_date,
            lag(rate) over(partition by from_cur, to_cur order by max(date)) lag_rate_grp,
            count(*) cnt,
            row_number() over(partition by from_cur, to_cur, case when count(*) >= 3 then 0 else 1 end order by max(date)) rn
        from (
            select
                t.*,
                row_number() over(partition by from_cur, to_cur order by date) rn1,
                row_number() over(partition by from_cur, to_cur, rate order by date) rn2         
            from mytable t
        ) t
        group by from_cur, to_cur, rate, rn1 - rn2
    ) t
    where cnt >= 3 and rn = 1
    order by from_cur, to_cur
    

    【讨论】:

    • 非常感谢您的快速帮助。我可能已经指定,但我的要求是到达 count>2 的第一个实例。我将尝试处理您的查询以到达我的预期输出。
    【解决方案2】:

    这是一个孤岛问题,但我会通过从日期中减去一个序列来解决它。然后聚合:

    select to_cur, from_cur, rate, min(date), max(date),
           count(*) as days_stale
    from (select r.*,
                 row_number() over (partition by to_cur, from_cur, rate order by date) as seqnum
          from rates r
         ) r
    group by (date - seqnum * interval '1' day)
    

    【讨论】:

      【解决方案3】:

      当值更改时,将行标记为 1,否则为 0。然后对这一列求和 (flg),您现在有连续的组 (grp)。使用grp 聚合、计数、显示最小和最大日期:

      dbfiddle demo

      select to_cur, from_cur, min(dt) dt_from, max(dt) dt_to, rate, count(1) cnt
        from (
          select dt, to_cur, from_cur, rate, 
                 sum(flg) over (partition by to_cur, from_cur order by dt) grp
            from (
              select dt, to_cur, from_cur, rate, 
                     case lag(rate) over (partition by to_cur, from_cur order by dt) 
                          when rate then 0 else 1 end flg
                from t))
        group by grp, to_cur, from_cur, rate
        order by from_cur, to_cur, min(dt)
      

      如果您想要任何特定的组后添加:

        having count(1) >= 3
      

      【讨论】:

      • 非常感谢您的快速帮助。我可能已经指定,但我的要求是到达 count>2 的第一个实例。我将尝试处理您的查询以到达我的预期输出。
      猜你喜欢
      • 2020-09-20
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      • 2018-07-04
      • 1970-01-01
      相关资源
      最近更新 更多