Oracle takes maximum or minimum value according to the repetitive data continuity date Date

Raw data:

 

 

 Results:

 

 

 FIG two comparison, if duplicate values ​​are not continuous process, we can use directly LEAD function trouble, but the result of the process out of the seemingly redundant.

My idea is that the raw data continuity date have good handle duplicate values, choose the smallest one, such as 2011/01/01 and 2012/01/01 values ​​are the same, but the date is continuous, so remove 2012/01/01, 2011/01/01 retained, so that the deadline for the deal out of date on line 4-1 that is 2012/12/30.

The following is the implementation code, there are better and more convenient welcome to learn together.

/*CREATE TABLE TB(PB_DATE DATE,SAVE_RATE VARCHAR2(10),LEN_RATE VARCHAR2(10));
INSERT INTO TB SELECT DATE'2010-01-01','8%','10%' FROM DUAL;
INSERT INTO TB SELECT DATE'2011-01-01','5%','7%' FROM DUAL;
INSERT INTO TB SELECT DATE'2012-01-01','5%','7%' FROM DUAL;
INSERT INTO TB SELECT DATE'2012-10-31','5%','6%' FROM DUAL;
INSERT INTO TB SELECT DATE'2013-01-01','5%','6%' FROM DUAL;
INSERT INTO TB SELECT DATE'2013-03-31','8%','9%' FROM DUAL;
INSERT INTO TB SELECT DATE'2013-09-01','8%','10%' FROM DUAL;
INSERT INTO TB SELECT DATE'2014-01-01','8%','9%' FROM DUAL;
INSERT INTO TB SELECT DATE'2015-01-01','6%','9%' FROM DUAL;
SELECT MIN(PB_DATE)START_DATE,MAX(END_DATE)END_DATE,SAVE_RATE,LEN_RATE FROM(
SELECT PB_DATE,LEAD(PB_DATE,1,DATE'9999-12-31')OVER(ORDER BY PB_DATE)-1 AS END_DATE,SAVE_RATE,LEN_RATE FROM TB)
GROUP BY SAVE_RATE,LEN_RATE;
SELECT T.*,MAX(PB_DATE)KEEP(DENSE_RANK LAST ORDER BY SAVE_RATE,LEN_RATE)OVER(PARTITION BY SAVE_RATE,LEN_RATE)AS RN FROM TB T ORDER BY 1 ;
SELECT * FROM TB;*/
/* Formatted on 2019/9/24 12:29:14 (QP5 v5.227.12220.39754) */
/* Formatted on 2019/9/24 12:41:16 (QP5 v5.227.12220.39754) */

实现代码,以上代码是造数脚本:
WITH TMP
AS ( SELECT PB_DATE,
SAVE_RATE,
LEN_RATE,
LEAD (PB_DATE, 1, DATE '9999-12-31') OVER (ORDER BY PB_DATE)
NEXT_DATE,
LAG (PB_DATE, 1, PB_DATE) OVER (ORDER BY PB_DATE) PRE_DATE,
LEAD (SAVE_RATE) OVER (ORDER BY PB_DATE) NEXT_SAVE,
LAG (SAVE_RATE) OVER (ORDER BY PB_DATE) PRE_SAVE,
LEAD (LEN_RATE) OVER (ORDER BY PB_DATE) NEXT_LEN,
LAG (LEN_RATE) OVER (ORDER BY PB_DATE) PRE_LEN
FROM TB
ORDER BY PB_DATE, SAVE_RATE, LEN_RATE),
TMP2
AS ( SELECT MAX (T.PB_DATE) AS PB_DATE, T.SAVE_RATE, T.LEN_RATE
FROM TMP T
WHERE (CASE
WHEN (SAVE_RATE = NEXT_SAVE AND LEN_RATE = NEXT_LEN)
OR (SAVE_RATE = PRE_SAVE AND LEN_RATE = PRE_LEN)
THEN
1
ELSE
0
END) = 1
GROUP BY T.SAVE_RATE, T.LEN_RATE
ORDER BY 1),
TMP3
AS (SELECT PB_DATE,SAVE_RATE,LEN_RATE
FROM TB T
WHERE NOT EXISTS
(SELECT NULL
FROM TMP2 R
WHERE R.SAVE_RATE = T.SAVE_RATE
AND R.LEN_RATE = T.LEN_RATE
AND R.PB_DATE = T.PB_DATE))
SELECT PB_DATE AS START_DATE,
LEAD (PB_DATE, 1, DATE '9999-12-31') OVER (ORDER BY PB_DATE) - 1
AS END_DATE,
SAVE_RATE,
LEN_RATE
FROM TMP3;

Guess you like

Origin www.cnblogs.com/guipeng/p/11577728.html