如何查询时间序列的状态变化?

ber*_*d_k 4 sql-server-2005 oracle

给定

create table rating (
    ID       int identity(1,1) primary key,
    PersonID int,
    Ratingdate date,
    rating   varchar(2)
);

insert into rating values ( 1, '2010-08-04' , 'A3');
insert into rating values ( 1, '2010-08-14' , 'A1');

insert into rating values ( 2, '2010-08-04' , 'G2');
insert into rating values ( 2, '2010-08-14' , 'G1');

insert into rating values ( 3, '2010-08-04' , 'G1');
insert into rating values ( 3, '2010-08-10' , 'G1');
insert into rating values ( 3, '2010-08-14' , 'G3');
insert into rating values ( 2, '2010-08-20' , 'G4');
Run Code Online (Sandbox Code Playgroud)

我想要一个查询,它返回所有行,其中给定人员的评级发生变化。例如,这里我想排除行( 3, '2010-08-10' , 'G1'),因为自( 3, '2010-08-04' , 'G1')以来评级没有改变。

我知道使用光标的解决方案,但我想知道是否可以在没有光标的情况下完成。我尝试了一些分析函数,但没有找到解决方案。

除了解决方案之外,请改进我描述问题的术语。我想这是一些标准任务。

编辑:

以下是连接请求将滞后和超前函数添加到 SQL Server 的链接。

请投票。

Jus*_*ave 5

看来你想要类似的东西

select *
  from (select person_id,
               rating_date,
               rating,
               lag(rating) over (partition by person_id
                                     order by rating_date) prior_rating
         from rating)
 where rating != prior_rating
    or prior_rating is null
 order by person_id, rating_date
Run Code Online (Sandbox Code Playgroud)

产生以下结果

SQL> ed
Wrote file afiedt.buf

  1  select person_id,
  2         rating_date,
  3         rating
  4    from (select person_id,
  5                 rating_date,
  6                 rating,
  7                 lag(rating) over (partition by person_id
  8                                       order by rating_date) prior_rating
  9           from rating)
 10   where rating != prior_rating
 11      or prior_rating is null
 12*  order by person_id, rating_date
SQL> /

 PERSON_ID RATING_DAT RATING
---------- ---------- --------
         1 2010-08-04 A3
         1 2010-08-14 A1
         2 2010-08-04 G2
         2 2010-08-14 G1
         2 2010-08-20 G4
         3 2010-08-04 G1
         3 2010-08-14 G3

7 rows selected.
Run Code Online (Sandbox Code Playgroud)