首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HiveQL和rank()

HiveQL和rank()
EN

Stack Overflow用户
提问于 2013-08-10 05:42:32
回答 2查看 33.4K关注 0票数 2

我不能理解HiveQL rank()。我在万维网上找到了一些排名自定义函数的实现,比如Edward's nice example。我可以加载和访问函数,但我不能让它们做我想做的事情。下面是一个详细的例子:

将UDF加载到CLI进程中:

代码语言:javascript
复制
$ javac -classpath /home/hadoop/hadoop/hadoop-core-1.0.4.jar:/home/hadoop/hive/lib/hive-exec-0.10.0.jar com/m6d/hiveudf/Rank2.java 
$ jar -cvf Rank2.jar com/m6d/hiveudf/Rank2.class
hive> ADD JAR /home/hadoop/MyDemo/Rank2.jar;
hive> CREATE TEMPORARY FUNCTION Rank2 AS 'com.m6d.hiveudf.Rank2'; 

创建一个表:

代码语言:javascript
复制
create table purchases (
  SalesRepId String, 
  PurchaseOrderId INT, 
  Amount INT
) 
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY ','
  LINES TERMINATED BY '\n';

从此CSV加载数据:

代码语言:javascript
复制
Jana,1,100
Nadia,2,200
Nadia,3,600
Daniel,4,80
Jana,5,120
William,6,170
Daniel,7,140

通过CLI执行以下操作:

代码语言:javascript
复制
LOAD DATA 
  LOCAL INPATH '/home/hadoop/MyDemo/purchases.csv'
  INTO TABLE purchases;

现在我可以看到我的顶级销售代表了:

代码语言:javascript
复制
select SalesRepId,sum(amount) as volume
from purchases
group by SalesRepId
ORDER BY volume DESC;

娜迪亚卖出了800美元,丹尼尔和贾娜都卖出了220美元,威廉卖出了170美元

代码语言:javascript
复制
SalesRep    Amount
--------    ------
Nadia       800
Daniel      220
Jana        220
William     170

现在我要做的就是给他们编号: Nadia排名第一,Daniel和Jana并列第二,William排名第四(而不是第三)。

代码语言:javascript
复制
select SalesRepId, V.volume,rank2(V.volume)
from 
(select SalesRepId,sum(amount) as volume
from purchases
group by SalesRepId
ORDER BY volume DESC) V;

这是我得到的,但不是我想要的:

代码语言:javascript
复制
SalesRep   Amount  Rank
--------   ------  ----
Nadia       800      1
Daniel      220      1
Jana        220      2
William     170      1

这是我想要的,但我不能让hive为我这样做:

代码语言:javascript
复制
SalesRep   Amount  Rank
--------   ------  ----
Nadia       800      1
Daniel      220      2
Jana        220      2
William     170      4

您能否帮助我使用正确的HiveQL对我的销售代表进行排名?

感谢JtheRocker的回复。他的改变导致了这个列表:

代码语言:javascript
复制
SalesRep   Amount  Rank
--------   ------  ----
William     170     1
Daniel      220     2
Jana        220     2
Nadia       800     3

稍微修改一下,将Nadia显示为第四位(而不是第三位):

代码语言:javascript
复制
private row_number;
@Override
public Object evaluate(DeferredObject[] currentKey) throws HiveException {
  row_number++;
  if (!sameAsPreviousKey(currentKey)) {
    this.counter = row_number;
    copyToPreviousKey(currentKey);
  }
return new Long(this.counter);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-12 23:23:58

通过配置单元0.11中引入的Windowing and Analytics functions,您可以使用:

代码语言:javascript
复制
select SalesRepId, volume as amount , rank() over (order by V.volume desc) as rank from 
(select SalesRepId,sum(amount) as volume from purchases group by SalesRepId) V;
票数 7
EN

Stack Overflow用户

发布于 2013-08-10 14:44:16

如果你有一个如下的评估函数,假设你直接从你提到的指南中使用这个函数,

代码语言:javascript
复制
private long counter;
@Override
  public Object evaluate(DeferredObject[] currentKey) throws HiveException {
    if (!sameAsPreviousKey(currentKey)) {
      this.counter = 0;
      copyToPreviousKey(currentKey);
    }

    return new Long(++this.counter);
  }

尝试将其更改为以下值,以便计数器在找到新卷时不会重置,相反,如果您找到相同的卷,则不会递增,而是仅在找到新卷时递增。

代码语言:javascript
复制
private long counter;
@Override
  public Object evaluate(DeferredObject[] currentKey) throws HiveException {
    //when not same as previous key you rather increment
    if (!sameAsPreviousKey(currentKey)) {
      this.counter ++;
      copyToPreviousKey(currentKey);
    }
    //else you keep the counter as it is
    return new Long(++this.counter);
 }

告诉我这是否有帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18156105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档