groupBy不支持Spark?

时间:2017-03-22 14:44:02

标签: hadoop apache-spark relational-database apache-spark-sql non-relational-database

表的设计是这样的:

id | val  |category
---------------- 
a1 |  10   | A
a1 |  30   | B
a1 |  20   | C
a2 |  5    | A
a2 |  7    | B
a2 |  2    | C
a3 | 50    | C
a3 | 60    | B
a3 | 90    | A

查询是这样的:

SELECT max(val), id, category FROM table GROUP BY id;

我确信这个查询可以在MySQL(在MySQL上测试),Oracle,MS SQL SERVER等关系数据库上运行。但是为什么它不能在Spark上运行?

我说对了#34; Spark对使用groupBy有一些限制吗?"我在mysql上测试了相同的桌面设计它完美无缺,但它给了我一个Spark上的错误,让我显示错误:

org.apache.spark.sql.AnalysisException: expression 'category' is neither present in the group by, nor is it an aggregate function. Add to group by or wrap in first() (or first_value) if you don't care which value you get.;
        at org.apache.spark.sql.catalyst.analysis.CheckAnalysis$class.failAnalysis(CheckAnalysis.scala:38)

在查看此错误后,Spark基本上建议使用first()函数或first_value()函数作为变通方法。所以,我试过,但我没有得到预期的输出,或者我不是100%确定输出是正确的。

  1. 是因为它是非关系型的吗?
  2. 我可以假设上述特定的groupBy案例不适用于其他非关系型数据库吗?
  3. 有人可以想到一个解决方法吗?一种更好的替代方法?
  4. 我做了一些研究,据说在某个地方"高于2.0的Spark版本不会出现这样的问题"。我使用的是Spark 1.6版本,Spark 2.0是否真的没有这样的问题?
  5. 如果我错了,请纠正我。非常感谢提前!!

3 个答案:

答案 0 :(得分:1)

按ID

对以下行进行分组时
id | val   | category
a1 |  10   | A
a1 |  30   | B
a1 |  20   | C

火花怎么知道它应该放出哪个类别? 第一个是随机的,最后一个?

MySQL对此更加冷静,以至于它返回它找到的第一个。 要在Spark中模仿这种行为,只需使用" first(category)"作为列定义。

答案 1 :(得分:1)

除非将其分组,否则无法预测字段类别。如果您要为每个类别和ID组合找到max(val),请尝试

SELECT max(val), id, category FROM table GROUP BY id, category;

您对此SQL的期望是什么?

spark-sql> desc sparktest;
id      string  NULL
val     int     NULL
category        string  NULL
Time taken: 3.217 seconds, Fetched 3 row(s)

spark-sql> SELECT max(val), id, category FROM sparktest GROUP BY id, category;
Time taken: 0.412 seconds

我的表中没有数据,你不是在Spark上工作是什么意思?

答案 2 :(得分:1)

你不懂SQL。这个问题与Spark无关。在标准SQL中,您无法选择不在GROUP BY中且在功能上不依赖于GROUP BY列的列。这是因为每组的该列通常有许多不同的值。 MySQL的非标准行为是从列中返回一个值。 (不保证特别是任何一个。)如果你想要一个特定的值并且它不是由聚合给出的,例如同一行中的那个与其他列的最大值相同,那么你需要编写适当的SQL查询。您的查询"正在使用MySQL"。你碰巧得到了那个结果。 (这恰好是你想要的。)MySQL可以为该组返回该列的任何值。

"此查询将起作用" &安培; "它完美运作"意思?你认为应该怎么做?什么是"预期的产出"?什么"它没有工作"意思?你不能说。

也许您希望组中具有最大val的行中的类别,但这不是您的查询所要求的。 the accepted answerSQL Select only rows with Max Value on a Column中解释了对此的正确查询:

  

乍一看......

     

您需要的只是GROUP BY子句,其中包含MAX聚合函数:

SELECT id, MAX(rev)
FROM YourTable
GROUP BY id
     

它从未如此简单,是吗?

     

我刚刚注意到您还需要content列。

     

这是SQL中非常常见的问题

  

实际上,StackOverflow社区已经创建了一个   单个标签只是为了处理这样的问题:   

可能the simplest variant among the answers是:

SELECT * 
FROM t1 WHERE (id,rev) IN 
( SELECT id, MAX(rev)
  FROM t1
  GROUP BY id
)