尝试为每个POLICY_ID选择最新的重复STATUS组的第一条记录。我该怎么办?
编辑/注意:如最后三行所示,状态重复可以超过两个。
数据视图:
所需的输出:
SQL用于数据:
--drop table mytable;
create table mytable (ROW_ID Number(5), POLICY_ID Number(5),
CHANGE_NO Number(5), STATUS VARCHAR(50), CHANGE_DATE DATE);
insert into mytable values ( 81, 1, 1, 'A', date '2018-01-01');
insert into mytable values ( 95, 1, 2, 'A', date '2018-01-02');
insert into mytable values ( 100, 1, 3, 'B', date '2018-01-03');
insert into mytable values ( 150, 1, 4, 'C', date '2018-01-04');
insert into mytable values ( 165, 1, 5, 'A', date '2018-01-05');
insert into mytable values ( 175, 1, 6, 'A', date '2018-01-06');
insert into mytable values ( 599, 2, 1, 'S', date '2018-01-11');
insert into mytable values ( 602, 2, 2, 'S', date '2018-01-12');
insert into mytable values ( 611, 2, 3, 'S', date '2018-01-13');
insert into mytable values ( 629, 2, 4, 'T', date '2018-01-14');
insert into mytable values ( 720, 2, 5, 'U', date '2018-01-15');
insert into mytable values ( 790, 2, 6, 'S', date '2018-01-16');
insert into mytable values ( 812, 2, 7, 'S', date '2018-01-17');
insert into mytable values ( 825, 2, 8, 'S', date '2018-01-18');
select * from mytable;
答案 0 :(得分:3)
嗯。 。 。
select t.*
from (select t.*,
row_number() over (partition by policy_id order by change_date asc) as seqnum
from t
where not exists (select 1
from t t2
where t2.policy_id = t.policy_id and
t2.status <> t.status and
t2.change_date > t.change_date
)
) t
where seqnum = 1;
内部子查询查找所有行-对于给定的策略号-以后没有状态不同的行。定义了最后一组记录。
然后它使用row_number()
来枚举行。这些外部查询为每个policy_number
选择第一行。
答案 1 :(得分:2)
您可以使用LEAD和LAG函数来识别以“重复”开始的行。条件 {status <> previous status and status = next status
将标识此类行。
SELECT *
FROM (
SELECT cte1.*, ROW_NUMBER() OVER (PARTITION BY POLICY_ID ORDER BY CHANGE_DATE DESC) AS rn
FROM (
SELECT mytable.*, CASE WHEN
STATUS <> LAG(STATUS, 1, '!') OVER (PARTITION BY POLICY_ID ORDER BY CHANGE_DATE) AND
STATUS = LEAD(STATUS) OVER (PARTITION BY POLICY_ID ORDER BY CHANGE_DATE)
THEN 1 END AS toselect
FROM mytable
) cte1
WHERE toselect = 1
) cte2
WHERE rn = 1
答案 2 :(得分:0)
如果您使用的是Oracle 12c
,则可以使用MATCH_RECOGNIZE
:
SELECT ROW_ID, POLICY_ID, CHANGE_NO, STATUS, CHANGE_DATE
FROM mytable
MATCH_RECOGNIZE (
PARTITION BY POLICY_ID
ORDER BY CHANGE_DATE
MEASURES MATCH_NUMBER() m,FIRST(R.ROW_ID) r
ALL ROWS PER MATCH
PATTERN (R+)
DEFINE R AS STATUS=NEXT(STATUS)
) MR
WHERE ROW_ID = R
ORDER BY ROW_NUMBER() OVER(PARTITION BY POLICY_ID ORDER BY M DESC)
FETCH FIRST 1 ROW WITH TIES;
或者:
SELECT *
FROM mytable
MATCH_RECOGNIZE (
PARTITION BY POLICY_ID
ORDER BY CHANGE_DATE DESC
MEASURES MATCH_NUMBER() m
,LAST(R.ROW_ID) ROW_ID
,LAST(R.STATUS) STATUS
,LAST(R.CHANGE_NO) CHANGE_NO
,LAST(R.CHANGE_DATE) CHANGE_DATE
ONE ROW PER MATCH
PATTERN (R+)
DEFINE R AS STATUS=PREV(STATUS)
) MR
WHERE M = 1
答案 3 :(得分:0)
使用match_recognize
的另一种方法:
select row_id, policy_id, change_no, status, change_date
from mytable
match_recognize (
partition by policy_id
order by change_date
measures
strt.row_id as row_id
, strt.change_no as change_no
, strt.change_date as change_date
, strt.status as status
pattern (strt unchanged* final)
define
unchanged as next(unchanged.status) = prev(unchanged.status)
, final as next(final.status) is null
) mr
order by mr.policy_id;