【问题标题】:How to Dense_Rank() Sets of Values that Repeat如何 Dense_Rank() 重复的值集
【发布时间】:2015-04-24 23:49:56
【问题描述】:

我有一张表T,如下所示:

T 表

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

由于PPP 值在OOO 值之后重复但在以后的日期,我不确定如何对其进行分组/排序,以便获得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;

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    我认为您需要两遍:首先找到代码更改的所有行,然后在此基础上建立一个组。

    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
    );
    

    【讨论】:

      【解决方案2】:

      如果我理解正确,您想按 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;
      

      您应该注意的唯一一件事是,最后的结果将被视为一个单独的排名,无论天气如何,它实际上是不是一个。

      【讨论】:

        【解决方案3】:

        递归解法也是可以的:

        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

        【讨论】:

          猜你喜欢
          • 2017-06-16
          • 1970-01-01
          • 1970-01-01
          • 2017-02-20
          • 2021-10-23
          • 1970-01-01
          • 1970-01-01
          • 2021-03-25
          • 1970-01-01
          相关资源
          最近更新 更多