【问题标题】:SQL - Compare rows based on date and transpose differenceSQL - 根据日期比较行并转置差异
【发布时间】:2021-05-12 14:38:47
【问题描述】:

场景:

'HIST'

RID VALUE HIST_DATE
1 V111 2019-01-01
1 V112 2020-02-11
1 V112 2020-03-08
1 V113 2020-04-11
1 V114 2021-03-15
2 V211 2020-04-11
2 V211 2021-03-16
3 V311 2019-05-01
3 V312 2020-01-01

预期输出:

RID VALUE_OLD VALUE_NEW
1 V113 V114

我想显示按 RID 分组的“VALUE”列中的行之间的差异,其中 HIST_DATE 在 '2020-03-31''2021-04-01' 之间强>

然后转置“VALUE_OLD”和“VALUE_NEW”列中的不同值。

注意:假设在这些日期之间只能出现 2 个不同的值

Oracle SQL

【问题讨论】:

  • 请解释逻辑。表中的其余值发生了什么变化?
  • 我只想知道两个时间检查点之间的值差异。其余差异不需要

标签: sql oracle


【解决方案1】:

另一种选择是使用 LAG/LEAD 分析功能:

  • LAG 从表中的前一行返回值。
  • LEAD 从表的下一行返回值。
select rid
    , LAG(hist_date) OVER(partition by rid order by hist_date ) as HIST_DATE_OLD 
    , hist_date  as HIST_DATE
    , LAG(value) OVER(partition by rid order by hist_date ) as VALUE_OLD 
    , value as VALUE_NEW
from hist

select rid
    , lead(hist_date) OVER(partition by rid order by hist_date desc) as HIST_DATE_OLD 
    , hist_date  as HIST_DATE
    , lead(value) OVER(partition by rid order by hist_date desc) as VALUE_OLD 
    , value as VALUE_NEW
from hist
order by rid, hist_date

然后您可以根据需要进行过滤和格式化

select rid, VALUE_OLD, VALUE_NEW from (
    select rid
       , TO_CHAR(lead(hist_date) OVER(partition by rid order by hist_date desc), 'YYYY-MM-DD') as HIST_DATE_OLD 
       , TO_CHAR(hist_date , 'YYYY-MM-DD') as HIST_DATE
       , lead(value) OVER(partition by rid order by hist_date desc) as VALUE_OLD 
       , value as VALUE_NEW
    from hist
    where HIST_DATE between '2020-03-31' and '2021-04-01'
    and   rid = 1  
order by rid, hist_date
)
where HIST_DATE_OLD IS NOT NULL

RID VALUE_OLD VALUE_NEW 
--- --------- --------- 
  1 V113      V114          
select * from (
    select rid
       , TO_CHAR(lead(hist_date) OVER(partition by rid order by hist_date desc), 'YYYY-MM-DD') as HIST_DATE_OLD 
       , TO_CHAR(hist_date , 'YYYY-MM-DD') as HIST_DATE
       , lead(value) OVER(partition by rid order by hist_date desc) as VALUE_OLD 
       , value as VALUE_NEW
    from hist
order by rid, hist_date
)
where HIST_DATE between '2020-03-31' and '2021-04-01'
    and   rid = 1  

RID HIST_DATE_OLD HIST_DATE  VALUE_OLD VALUE_NEW 
--- ------------- ---------- --------- --------- 
  1 2020-03-08    2020-04-11 V112      V113      
  1 2020-04-11    2021-03-15 V113      V114      

注意主SELECT内外的过滤器

  • 在外面,您在执行 LAG/LEAD 操作后进行过滤(上图)
  • 在内部,您在执行 LAG/LEAD 操作之前进行过滤(如下)
RID HIST_DATE_OLD HIST_DATE  VALUE_OLD VALUE_NEW 
--- ------------- ---------- --------- --------- 
  1               2020-04-11           V113      
  1 2020-04-11    2021-03-15 V113      V114      

【讨论】:

    【解决方案2】:

    假设在这些日期之间只能出现 2 个不同的值

     select distinct RID, 
            first_value(VALUE) over(order by HIST_DATE) VALUE_OLD,
            first_value(VALUE) over(order by HIST_DATE desc) VALUE_NEW
     from HIST
     where HIST_DATE between  date '2020-03-31' and date '2021-04-01'
    
        
    

    【讨论】:

      【解决方案3】:

      你必须:

      1. 查找每个 rid (newvals) 的最后 hist_date
      2. 查找最后一个 (newvals) 之前的每个 rid (oldvals) 的 last hist_date
      3. 读取历史表以查找每个消除的新值
      4. 读取历史表以查找每个消除的先前 val

      无论是否有其他较旧的值,您总是显示每个消除的最后两个值。

      SELECT
          n.rid,
          o.value AS value_old,
          n.value AS value_new
      FROM
          (
              SELECT
                  rid,
                  MAX(hist_date) AS DATE
              FROM
                  hist
              GROUP BY
                  rid
          )
          newvals,
          (
              SELECT
                  hist.rid,
                  MAX(hist_date) AS DATE
              FROM
                  hist,
                  (
                      SELECT
                          rid,
                          MAX(hist_date) AS DATE
                      FROM
                          hist
                      GROUP BY
                          rid
                  )
                  newvals
              WHERE
                  hist.rid=newvals.rid
              AND hist.hist_date<newvals.date
              GROUP BY
                  hist.rid
          )
          oldvals,
          hist n,
          hist o
      WHERE
          n.rid=o.rid
      and n.rid=newvals.rid
      and n.rid=oldvals.rid
      AND n.hist_date=newvals.date
      AND o.hist_date=oldvals.date
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-18
        • 1970-01-01
        • 2014-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多