SQL上次状态更改日期

时间:2017-05-01 21:49:19

标签: sql oracle date

我正在尝试获取上次状态更改的日期。下面是一个示例数据表。 简而言之,我想查询每个PRODUCT_ID的最新STATUS(按CHANGE_NO排序)的最小DATE值。提到的值是填充黄色的值。

enter image description here

到目前为止,我只能获得每种产品的最新日期。

SELECT
  *
FROM
  (
    SELECT
      PRODUCT_ID, CHANGE_NO, STATUS, DATE
      ,MAX(CHANGE_NO) OVER(PARTITION BY PRODUCT_ID) MAX_CHANGE_NO
    FROM TABLE
    ORDER BY PRODUCT_ID, CHANGE_NO
  ) 
WHERE   MAX_CHANGE_NO = CHANGE_NO

如果已经有类似案件的问题/答案,请分享链接;我已经搜索过但无法找到任何内容。

注意:我使用的是Oracle SQL。

提前致谢。

2 个答案:

答案 0 :(得分:1)

这是使用分析函数(避免连接)的一种方法。

with
     test_data ( product_id, change_no, status, dt ) as (
       select 1, 1, 'A', date '2016-10-10' from dual union all
       select 1, 2, 'B', date '2016-10-11' from dual union all
       select 1, 3, 'C', date '2016-10-12' from dual union all
       select 1, 4, 'D', date '2016-10-13' from dual union all
       select 2, 1, 'Y', date '2016-02-02' from dual union all
       select 2, 2, 'X', date '2016-02-03' from dual union all
       select 2, 3, 'X', date '2016-02-04' from dual union all
       select 3, 1, 'H', date '2016-06-20' from dual union all
       select 3, 2, 'G', date '2016-06-21' from dual union all
       select 3, 3, 'T', date '2016-06-22' from dual union all
       select 3, 4, 'K', date '2016-06-23' from dual union all
       select 3, 5, 'K', date '2016-06-24' from dual union all
       select 3, 6, 'K', date '2016-06-25' from dual
     )
-- End of test data (not part of the solution). SQL query begins below this line.
select   product_id,
         max(status) keep (dense_rank last order by change_no) as status,
         max(dt) as dt
from     (
           select product_id, change_no, status, dt,
                  case when lead(status) over (partition by product_id 
                                               order by change_no desc)
                            = status then 0 else 1 end as flag
           from   test_data
         )
where    flag = 1
group by product_id
order by product_id    --    if needed
;

<强>输出

PRODUCT_ID  STATUS  DT
----------  ------  ----------
         1  D       13/10/2016
         2  X       03/02/2016
         3  K       23/06/2016

答案 1 :(得分:0)

SELECT * FROM (
SELECT PRODUCT_ID, CHANGE_NO, STATUS,DATE, MIN(DATE) OVER(PARTITION BY PRODUCT_ID,STATUS) as MIN_DATE_OF_LATEST_STATUS
FROM (SELECT PRODUCT_ID, CHANGE_NO, STATUS, DATE
      ,FIRST_VALUE(STATUS) OVER(PARTITION BY PRODUCT_ID ORDER BY CHANGE_NO DESC) LATEST_STATUS
     FROM TABLE
     ) T
     WHERE STATUS = LATEST_STATUS
              ) T
WHERE DATE = MIN_DATE_OF_LATEST_STATUS
  • 使用FIRST_VALUE窗口功能获取每个product_id的最新状态
  • 获取这些状态行的MIN日期
  • 最后获取min_date = date
  • 的行

如果最终结果中不需要change_no,则可以将查询简化为

SELECT PRODUCT_ID, STATUS, MIN(DATE) as MIN_DATE_OF_LATEST_STATUS
FROM (SELECT PRODUCT_ID, CHANGE_NO, STATUS, DATE
      ,FIRST_VALUE(STATUS) OVER(PARTITION BY PRODUCT_ID ORDER BY CHANGE_NO DESC) LATEST_STATUS
     FROM TABLE
     ) T
WHERE STATUS = LATEST_STATUS
GROUP BY PRODUCT_ID, STATUS