【问题标题】:Oracle Rank() within (sub)group(子)组内的 Oracle Rank()
【发布时间】:2017-09-17 07:45:29
【问题描述】:

我正在尝试在子组中获得正确的排名,但结果有问题。我需要根据时间戳获得每次组更改的排名。

例如,使用这个表:

create table syntrans (
    transid     number,
    launchtime  timestamp,
    status      varchar2(10)
);

insert into syntrans values ( 1, '19-APR-17 07.34.05.824875 PM','FAIL');
insert into syntrans values (  1, '19-APR-17 07.34.06.828753 PM','FAIL');
insert into syntrans values (  1, '19-APR-17 07.34.08.567579 PM','SUCCESS');
insert into syntrans values (  1, '19-APR-17 08.07.31.731745 PM','SUCCESS');
insert into syntrans values (  1, '19-APR-17 08.07.32.735582 PM','SUCCESS');
insert into syntrans values (  2, '19-APR-17 08.17.51.332804 PM','FAIL');
insert into syntrans values (  2, '19-APR-17 08.17.52.336530 PM','FAIL');
insert into syntrans values (  2, '19-APR-17 08.19.27.993327 PM','SUCCESS');
insert into syntrans values (  2, '19-APR-17 08.25.54.860077 PM','FAIL');
insert into syntrans values (  2, '19-APR-17 08.25.55.862830 PM','SUCCESS');

我目前得到的是

SELECT transid,
       launchtime,
       status,
       rank() over (partition by status order by launchtime) rnk
  FROM syntrans 
 order by transid, launchtime, status;

   TRANSID LAUNCHTIME                     STATUS            RNK
---------- ------------------------------ ---------- ----------
         1 19-APR-17 07.34.05.824875 PM   FAIL                1
         1 19-APR-17 07.34.06.828753 PM   FAIL                2
         1 19-APR-17 07.34.08.567579 PM   SUCCESS             1
         1 19-APR-17 08.07.31.731745 PM   SUCCESS             2
         1 19-APR-17 08.07.32.735582 PM   SUCCESS             3
         2 19-APR-17 08.17.51.332804 PM   FAIL                3
         2 19-APR-17 08.17.52.336530 PM   FAIL                4
         2 19-APR-17 08.19.27.993327 PM   SUCCESS             4
         2 19-APR-17 08.25.54.860077 PM   FAIL                5
         2 19-APR-17 08.25.55.862830 PM   SUCCESS             5

需要的输出是这样的:

   TRANSID LAUNCHTIME                     STATUS            RNK
---------- ------------------------------ ---------- ----------
         1 19-APR-17 07.34.05.824875 PM   FAIL                1
         1 19-APR-17 07.34.06.828753 PM   FAIL                2
         1 19-APR-17 07.34.08.567579 PM   SUCCESS             1
         1 19-APR-17 08.07.31.731745 PM   SUCCESS             2
         1 19-APR-17 08.07.32.735582 PM   SUCCESS             3
         2 19-APR-17 08.17.51.332804 PM   FAIL                1
         2 19-APR-17 08.17.52.336530 PM   FAIL                2
         2 19-APR-17 08.19.27.993327 PM   SUCCESS             1
         2 19-APR-17 08.25.54.860077 PM   FAIL                1
         2 19-APR-17 08.25.55.862830 PM   SUCCESS             1

...每次状态值更改时“排名”从这里开始(按日期排序)。我知道我得到的输出是按整体状态组排名的,但我无法找到任何函数组合来获得所需的输出。

几乎明白了,但不完全:

SELECT transid, launchtime, status, rnk
  FROM (SELECT transid,
              status,
              launchtime,
              RANK() OVER (PARTITION BY transid, status ORDER BY launchtime) rnk
         FROM syntrans )
ORDER BY transid, launchtime;

【问题讨论】:

    标签: sql oracle oracle12c rank


    【解决方案1】:

    您可以使用行号差异的方法将连续的相同状态行分类为一组。 (运行内部查询以查看组是如何分配的。)然后对这些组使用row_number

    SELECT transid, launchtime, status
    ,ROW_NUMBER() over(PARTITION BY transid,grp ORDER BY launchtime) as rnk
    FROM (SELECT  transid,
                  status,
                  launchtime,
                  ROW_NUMBER() OVER (PARTITION BY transid ORDER BY launchtime)
                  -ROW_NUMBER() OVER (PARTITION BY transid, status ORDER BY launchtime) as grp
             FROM syntrans) t
    

    【讨论】:

    • 是的,这就是我需要的输出。我曾尝试过将 decode() 和 lag() 结合起来,但没想到会像这样减去 row_number() 输出 - 谢谢!
    • @dlivings - 如果你喜欢通过阅读来学习,请搜索“Tabibitosan 方法” - 你会发现很多这种技术的例子(这就是它的名称)。事实证明,它在许多令人惊讶的情况下都非常有用。
    • @mathguy - 谢谢,我不知道该方法有名称。已经找到了其他东西我可以重新使用它(除了 OP)并减少相当多的复杂性......
    猜你喜欢
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    相关资源
    最近更新 更多