rank() 按 count(*) 对一组项目进行排序

Posted

技术标签:

【中文标题】rank() 按 count(*) 对一组项目进行排序【英文标题】:rank() a group of items by count(*) 【发布时间】:2015-12-06 19:08:53 【问题描述】:

我在使用 Oracle 分析功能时遇到了一些问题,需要帮助。 这是一个通用示例:

create table test (item varchar2(10), value varchar2(10));

insert into test values ('item1','value1');
insert into test values ('item1','value1');
insert into test values ('item1','value1');
insert into test values ('item1','value1');
insert into test values ('item1','value1');
insert into test values ('item1','value2');
insert into test values ('item1','value2');
insert into test values ('item3','value2');
insert into test values ('item3','value2');
insert into test values ('item3','value2');
insert into test values ('item5','value1');
insert into test values ('item5','value1');
insert into test values ('item5','value1');
insert into test values ('item5','value1');
insert into test values ('item5','value1');
insert into test values ('item5','value1');
insert into test values ('item5','value1');
insert into test values ('item5','value2');
insert into test values ('item5','value2');
insert into test values ('item5','value2');

select item, value, count(*) c, 
       sum(count(*)) over () total, 
       sum(count(*)) over (partition by item) total_by_item,
       dense_rank() over (order by count(*) desc) dense_rank
  from test 
 group by item, value 
 order by 5 desc;

查询的结果是:

ITEM       VALUE       C      TOTAL  TOTAL_BY_ITEM DENSE_RANK
---------- ---------- -- ---------- -------------- ----------
item5      value1      7         20             10          1
item5      value2      3         20             10          3
item1      value2      2         20              7          4
item1      value1      5         20              7          2
item3      value2      3         20              3          3

如何获得按 TOTAL_BY_ITEM 排名的项目?所以它看起来像这样:

ITEM       VALUE       C      TOTAL  TOTAL_BY_ITEM WHAT_I_NEED
---------- ---------- -- ---------- -------------- -----------
item5      value1      7         20             10           1
item5      value2      3         20             10           1
item1      value2      2         20              7           2
item1      value1      5         20              7           2
item3      value2      3         20              3           3

是否可以在没有另一个连接或子查询的情况下实现这一点?我有一种感觉,这是可能的。我自然认为它必须是这样的:dense_rank(count(*)) over (partition by item),就像我用来获取第 5 列的分析 SUM,但它不起作用。

【问题讨论】:

【参考方案1】:

我认为这不是您要搜索的内容,但仅供参考,无需子查询,您可以使用 MODEL 子句获得相同的结果:

select item, value, c, total, total_by_item, what_i_need
from test 
group by item, value
model
  dimension by (row_number() over (order by null) d)
  measures (
    item, value,
    count(*) c,
    sum(count(*)) over () total,
    sum(count(*)) over (partition by item) total_by_item,
    1 what_i_need
  )
  rules (
    what_i_need[any] = dense_rank() over (order by total_by_item[cv()] desc)
  )
order by 5 desc;

我不认为没有子查询你可以实现它。

【讨论】:

您好,谢谢您的回答。这不是我想要的,但非常接近。明天我会在真实数据上试试这个。你真的认为没有子查询就无法实现我所需要的吗?我从未使用过 MODEL 子句。是否有任何关于其性能的细节? MODEL 适用于复杂的转换和报告规则,例如当需要行值之间的依赖关系时。在您的情况下,子查询和两个窗口函数会更简单。由于您没有任何自然的单一维度,因此我需要第三个分析函数来生成替代维度 d。现在我认为最好使用dimension by (item || value d) 而不是使用ROW_NUMBER。子查询有什么问题? 你知道,现在我开始认为子查询不会有问题。明天我将测试这两种变体的速度。我相信模型和子查询的速度应该很接近吧?无论如何,非常感谢你的想法! 我肯定会选择子查询,它的代码更简洁,而且我认为在这种情况下更快。 我想我会的。这里的问题是我有一个子查询,我在其中读取了同一个表(在我的示例中为测试)两次,并且在某些情况下整体性能很糟糕。现在我不必第二次阅读同一张表,只需阅读结果即可。我不知何故错过了这部分,因此提出了问题。

以上是关于rank() 按 count(*) 对一组项目进行排序的主要内容,如果未能解决你的问题,请参考以下文章

按条件分组和计数

[HIVE] rank() dense_rank() row_number()的学习

开窗函数和row_number()

C语言链表中如何实现对一组数据进行排序?

具有多个变量的用户定义函数? / 对一系列命名列进行操作的函数(而不是按数字索引)?

Day458.聚合函数 -mysql