我有一个表,需要根据某些列的相同共享值将当前事件与先前事件进行匹配。这是一个简化的示例:
e5028218-eea8-41b0-951c-ccd006f35bc8 1533648871.77204 braden NULL
120cd0fd-15d2-40e8-8285-53499a5aa294 1533648871.77262 gracelyn NULL
78a40fdd-f361-4929-ad6b-1ee411300c84 1533648871.77274 cruz NULL
ec463751-22ca-4776-9cff-f7a332bab8b6 1533648871.77285 bob NULL
b824c942-bfc5-4cee-90d3-26686e7ace2e 1533648871.77296 amara NULL
527170df-1499-4cfa-be2c-f484a8cf01f4 1533648871.77307 jerry NULL
2116e07b-14ea-4760-be3e-f9db7f051831 1533648871.77318 bob ec463751-22ca-4776-9cff-f7a332bab8b6
951df6c9-5a7b-4208-a8bb-8075a37f61ba 1533648871.7733 gael NULL
3859a175-f16b-4fd1-9e66-03f5f3b295f4 1533648871.77341 bob 2116e07b-14ea-4760-be3e-f9db7f051831
6d60a51b-c822-45b3-8a4a-5f535372e11b 1533648871.77351 jaime NULL
0becf14b-442b-4ac7-9819-2144c50bc611 1533648871.77362 brock NULL
001eea59-751f-4b51-ba1d-f706190cbae3 1533648871.77373 kyleigh NULL
Bob有几个与他相关联的transID
,因此对于每一行,transID
列中显示的是timeStamp
,其中transIDPred
来自前几行。对于其他行,该列应保持为空。
通过运行这样的简单SQL语句,我可以在MySQL中使用transIDPred
轻松地创建一个表:
create table Events1 as
select
transID,
timeStamp,
principal,
(select transID from Events sub
where (sub.principal = main.principal and sub.timeStamp < main.timeStamp)
order by timeStamp desc limit 1) as
transIDPred
from Events as main order by transID asc
但是,如果我尝试在SparkSQL中运行类似的查询,则会出现以下错误:
Exception in thread "main" org.apache.spark.sql.AnalysisException: Accessing outer query column is not allowed in....
根据这篇有用的文章,我设法部分重写了与该查询相对应的Spark(JAVA): How to write a nested query?
但是我无法使其完全正常工作,因为我不知道如何只选择最新的前身ID,而不是全部。
代码看起来像这样:
Dataset<Row> ds = ... (load from SQL)
ds.createOrReplaceTempView("Events");
Dataset<Row> dsSub = ds
.withColumnRenamed("transID", "subTransID")
.withColumnRenamed("timeStamp", "subTimeStamp")
.withColumnRenamed("principal", "subPrincipal")
.orderBy(org.apache.spark.sql.functions.desc("subTimeStamp"));
Dataset<Row> trnJoin = ds
.join(dsSub)
.where("subPrincipal = principal and timeStamp > subTimeStamp")
.select("transID", "timeStamp", "principal", "subTransID");
但是我不知道如何将1的限制应用于子查询(似乎Spark只能将.limit()应用于查询的外部,这似乎理解为这种情况?在这种情况下,它只是创建为Dataset只能有1行。否则,如果没有.limit()子句,它将匹配所有匹配的行,而不是所有前任中的最新行。我需要在JAVA中做到这一点。
谢谢您的任何建议!另外,如果您对大型数据集(例如1亿至10亿个元素)上的SparkSQL中的这种连接的潜在性能有任何看法-甚至建议在Spark中执行此操作,还是我应该针对整个数据库? >