NTILE函数在Spark SQL 1.5中不起作用

时间:2015-12-15 11:23:05

标签: apache-spark apache-spark-sql quantile

我在像这样的简单数据集上测试NTILE函数:

(id:string,value:double)
A 10
B 3
C 4
D 4
E 4
F 30
C 30
D 10
A 4
H 4

针对HIVE运行以下查询(在MapReduce上)

SELECT tmp.id, tmp.sum_val, NTILE(4) OVER (ORDER BY tmp.sum_val) AS quartile FROM (SELECT id, sum(value) AS sum_val FROM testntile GROUP BY id) AS tmp

可以正常使用以下结果:

(id,sum_val,quartile)
B 3 1
H 4 1
E 4 2
D 14 2
A 14 3
F 30 3
C 34 4

在Spark上对Hive运行相同的查询(v 1.5)仍然可以正常工作。

针对Spark SQL 1.5(CDH 5.5.1)运行相同的查询

val result = sqlContext.sql("SELECT tmp.id, tmp.sum_val, NTILE(4) OVER (ORDER BY tmp.sum_val) AS quartile FROM (SELECT id, sum(value) AS sum_val FROM testntile GROUP BY id) AS tmp")
result.collect().foreach(println)

我得到以下错误结果:

[B,3.0,0]
[E,4.0,0]
[H,4.0,0]
[A,14.0,0]
[D,14.0,0]
[F,30.0,0]
[C,34.0,0]

重要提示:结果不具有确定性,因为“有时”会返回正确的值

直接在数据框上运行相同的算法

val x = sqlContext.sql("select id, sum(value) as sum_val from testntile group by id")
val w = Window.partitionBy("id").orderBy("sum_val")
val resultDF = x.select( x("id"),x("sum_val"), ntile(4).over(w) )

仍会返回错误的结果。

我做错了吗?有任何想法吗?提前感谢您的回答。

1 个答案:

答案 0 :(得分:0)

如果您使用Window.partitionBy("id").orderBy("sum_val"),则将按id进行分组,然后再应用ntile函数。因此,通过这种方式,每个组都有一个元素,并且ntile会为每个id应用相同的值。

为了获得第一个结果,您需要删除partitionBy("id")并仅使用Window.orderBy("sum_val")

这是我修改您的代码的方式:

val w = Window.orderBy("sum_val")
val resultDF = x.orderBy("sum_val").select( x("id"),x("sum_val"), ntile(4).over(w) )

这是resultDF.show()的印刷品:

+---+-------+-----+ | id|sum_val|ntile| +---+-------+-----+ | B| 3| 1| | E| 4| 1| | H| 4| 2| | D| 14| 2| | A| 14| 3| | F| 30| 3| | C| 34| 4| +---+-------+-----+