获取变更日期

时间:2015-05-18 15:27:46

标签: sql oracle

我有一个包含日期和状态的表格。我希望获得状态更改为最新状态的日期。样本数据:

DATE        STATUS
01/01/2000  P
02/01/2000  A
03/01/2000  C
04/01/2000  A
05/01/2000  A
06/01/2000  A

因此,在这种情况下,最近的状态是A,并在04/01/2000更改为此状态。 (在这种情况下应该忽略02/01/2000行)

有关如何选择此行的任何建议?

3 个答案:

答案 0 :(得分:0)

起初,我误解了这个问题。您需要获取最后一次状态的最早日期。

您可以使用技巧对相似状态的序列进行分组 - 行数的差异。对于相同的序列,差异(在下面的查询中)是不变的。然后,您可以使用聚合来获取最小日期并选择最新日期:

def julian_day(dt):
    jan1 = dt.replace(month=1, day=1)
    return 1 + (dt - jan1).days

编辑:

无论如何,正确的方法是使用select mindate from (select min(date) as mindate from (select t.*, row_number() over (order by date) as seqnum1, row_number() over (partition by status order by date) as seqnum2 from table t ) t group by status, (seqnum1 - seqnum2) order by mindate desc ) t where rownum = 1

lag()

Here是SQL小提琴。

答案 1 :(得分:0)

你可以使用lag或lead来做到这一点。在这里,我使用lead,按日期降序排序以查找上一个状态日期(如果它为null我只提供日期,如果只有一条记录则需要该日期。)

select max(date)
from (
    select status, date, nvl(lead(status) over (order by date desc),date) as previous_status
    from t
    order by date desc
)
where status <> previous_status;

答案 2 :(得分:0)

这样的事情应该做到这一点:

with sample_data as (select to_date('01/01/2000', 'dd/mm/yyyy') dt, 'P' status from dual union all
                     select to_date('02/01/2000', 'dd/mm/yyyy') dt, 'A' status from dual union all
                     select to_date('03/01/2000', 'dd/mm/yyyy') dt, 'C' status from dual union all
                     select to_date('04/01/2000', 'dd/mm/yyyy') dt, 'A' status from dual union all
                     select to_date('05/01/2000', 'dd/mm/yyyy') dt, 'A' status from dual union all
                     select to_date('06/01/2000', 'dd/mm/yyyy') dt, 'A' status from dual),
        results1 as (select dt,
                            status,
                            row_number() over (order by dt) - row_number() over (partition by status order by dt) grp
                     from   sample_data),
        results2 as (select status, min(dt) min_dt, grp, max(min(dt)) over () max_min_dt
                     from   results1
                     group by status, grp)
select status, min_dt
from   results2
where  min_dt = max_min_dt;

STATUS MIN_DT    
------ ----------
A      04/01/2000