2015-04-24 24 views
0

我有一个表T值,如设置如下:如何DENSE_RANK(),即重复

牛逼表

EMPLID CODE DT 
101  PPP  01-JAN-15 
101  PPP  02-JAN-15 
101  PPP  03-JAN-15 
101  OOO  04-JAN-15 
101  OOO  05-JAN-15 
101  PPP  06-JAN-15 
101  PPP  07-JAN-15 
101  PPP  08-JAN-15 
101  PPP  09-JAN-15 

我想要的是像下面这样的结果:

EMPLID CODE RNK DT 
101  PPP  1  01-JAN-15 
101  PPP  1  02-JAN-15 
101  PPP  1  03-JAN-15 
101  OOO  2  04-JAN-15 
101  OOO  2  05-JAN-15 
101  PPP  3  06-JAN-15 
101  PPP  3  07-JAN-15 
101  PPP  3  08-JAN-15 
101  PPP  3  09-JAN-15 

但我似乎只能得到如下结果:

SELECT EMPLID, CODE, DENSE_RANK() OVER(ORDER BY CODE) AS RNK, DT 
FROM T; 


EMPLID CODE RNK DT 
101  OOO  1  05-JAN-15 
101  OOO  1  04-JAN-15 
101  PPP  2  03-JAN-15 
101  PPP  2  08-JAN-15 
101  PPP  2  09-JAN-15 
101  PPP  2  06-JAN-15 
101  PPP  2  07-JAN-15 
101  PPP  2  02-JAN-15 
101  PPP  2  01-JAN-15 

由于PPPOOO值后重复,但在稍后的日期,我不知道如何组/为了它,这样我得到的RNK场考虑第二组PPP值的为第三组。

这里是表,使这更容易一点的代码:

WITH 
T AS(
SELECT '101' AS EMPLID, 'PPP' AS CODE, '01-JAN-15' AS DT FROM DUAL 
UNION ALL 
SELECT '101', 'PPP', '02-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'PPP', '03-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'OOO', '04-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'OOO', '05-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'PPP', '06-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'PPP', '07-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'PPP', '08-JAN-15' FROM DUAL 
UNION ALL 
SELECT '101', 'PPP', '09-JAN-15' FROM DUAL 
) 
SELECT * 
FROM T; 

回答

3

我想你需要两遍:首先找到的所有行代码更改,那么建立在这个群体。

select emplid, code, sum(change) over (order by dt) as rnk, dt 
from 
(
    select 
    emplid, 
    code, 
    case when lag(code) over (order by dt) = code then 0 else 1 end as change, 
    dt 
    from t 
    order by dt 
); 
+0

哇,非常酷。谢谢! – BarrettNashville

0

如果我理解正确,你想要通过dt命令结果。您可以设置标志,每改变行,然后总结标志达该行,这将给你相同的结果DENSE_RANK:

SELECT 
    sel2.emplid, 
    sel2.code, 
    SUM (sel2.flg) OVER (ORDER BY sel2.dt ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) rnk, 
    sel2.dt 
FROM 
    (SELECT 
     sel1.emplid, 
     sel1.code, 
     CASE WHEN sel1.code = sel1.code_lag THEN 0 ELSE 1 END flg, 
     sel1.dt 
    FROM  
     (SELECT emplid, code, dt, LAG(code,1,'XXX') OVER (ORDER BY dt) code_lag 
     FROM T 
    ) sel1 
) sel2 
ORDER BY dt; 

你应该知道的唯一的事情是,最后的结果会被视为一个单独的等级,无论它实际上是否是一个天气。

0

递归解决方案也是可能的:

with s (u, s, a, n) as (
    select emplid, code, 1, dt from t where dt = date '2015-01-01' 
    union all select emplid, code, a+decode(code, s, 0, 1), dt from t join s on dt=n+1) 
select * from s 

SQLFiddle