重用“ GROUP BY”子句中选择表达式的结果?

lee*_*wah 4 mysql scala apache-spark apache-spark-sql spark-dataframe

在MySQL中,我可以这样查询:

select  
    cast(from_unixtime(t.time, '%Y-%m-%d %H:00') as datetime) as timeHour
    , ... 
from
    some_table t 
group by
    timeHour, ...
order by
    timeHour, ...
Run Code Online (Sandbox Code Playgroud)

其中timeHourGROUP BY为一个选择的表达的结果。

但是我只是尝试了一个类似于中的查询Sqark SQL,但出现了错误

Error: org.apache.spark.sql.AnalysisException: 
cannot resolve '`timeHour`' given input columns: ...
Run Code Online (Sandbox Code Playgroud)

我的查询Spark SQL是这样的:

select  
      cast(t.unixTime as timestamp) as timeHour
    , ...
from
    another_table as t
group by
    timeHour, ...
order by
    timeHour, ...
Run Code Online (Sandbox Code Playgroud)

这种结构可能Spark SQL吗?

mrs*_*vas 5

Spark SQL中可以使用这种构造吗?

是的,是。您可以通过两种方式使其在Spark SQL中运行,以在GROUP BYORDER BY子句中使用新列

使用子查询的方法1:

SELECT timeHour, someThing FROM (SELECT  
      from_unixtime((starttime/1000)) AS timeHour
    , sum(...)                          AS someThing
    , starttime
FROM
    some_table) 
WHERE
    starttime >= 1000*unix_timestamp('2017-09-16 00:00:00')
      AND starttime <= 1000*unix_timestamp('2017-09-16 04:00:00')
GROUP BY
    timeHour
ORDER BY
    timeHour
LIMIT 10;
Run Code Online (Sandbox Code Playgroud)

方法2使用WITH //优雅的方式:

-- create alias 
WITH table_aliase AS(SELECT  
      from_unixtime((starttime/1000)) AS timeHour
    , sum(...)                          AS someThing
    , starttime
FROM
    some_table)

-- use the same alias as table
SELECT timeHour, someThing FROM table_aliase
WHERE
    starttime >= 1000*unix_timestamp('2017-09-16 00:00:00')
      AND starttime <= 1000*unix_timestamp('2017-09-16 04:00:00')
GROUP BY
    timeHour
ORDER BY
    timeHour
LIMIT 10;
Run Code Online (Sandbox Code Playgroud)

在Scala中使用Spark DataFrame(wo SQL)API的替代方法:

// This code may need additional import to work well

val df = .... //load the actual table as df

import org.apache.spark.sql.functions._

df.withColumn("timeHour", from_unixtime($"starttime"/1000))
  .groupBy($"timeHour")
  .agg(sum("...").as("someThing"))
  .orderBy($"timeHour")
  .show()

//another way - as per eliasah comment
df.groupBy(from_unixtime($"starttime"/1000).as("timeHour"))
  .agg(sum("...").as("someThing"))
  .orderBy($"timeHour")
  .show()
Run Code Online (Sandbox Code Playgroud)