我们必须编写一个SparkSQL查询来获取特定值的上一行和下一行。 让我们说,我们在Cassandra的表结构如下所示
id, timestamp
1, 100
2,200
3,300
4,400
现在我必须写一个Spark查询来只获得两行,而在这两行中,第一行的值应该小于300,即(2,200)和第二行的值应该是大于300即(4,400)。而且由于数据量很大,我不想按操作执行订单。在数据量很大的情况下,操作的顺序会很慢。 我们可以理解这样的要求,假设我想要从表格的前一个和下一行获取时间戳值为: - 对于第一行:应小于300,因此预期行为(2,200) 对于第二行:应该大于300,因此预期的行是(4,400) 输出应该如下所示
2,200
4,400
但是这应该在没有操作的情况下执行。
答案 0 :(得分:1)
您可以使用RDD API,创建一个向上或向下移动的索引列来模拟滑动操作:
#Obtain an index for each element
df_id = df.rdd.zipWithIndex()\
.map(lambda row: Row(id=row[0].id, timestamp=row[0].timestamp, idx=row[1]))\
.toDF()
previousDF = df_id.rdd\
.map(lambda row: Row(previous_id=row.id, previous_timestamp=row.timestamp, idx=row.idx+1))\
.toDF()
nextDF = df_id.rdd\
.map(lambda row: Row(next_id=row.id, next_timestamp=row.timestamp, idx=row.idx-1))\
.toDF()
现在,在idx
列上执行联接,将原始DF与其他人联合起来:
df_id.join(previousDF, on='idx')\
.join(nextDF, on='idx')\
.show()
结果如下:
+---+---+---------+-----------+------------------+-------+--------------+
|idx| id|timestamp|previous_id|previous_timestamp|next_id|next_timestamp|
+---+---+---------+-----------+------------------+-------+--------------+
| 1| 2| 200| 1| 100| 3| 300|
| 2| 3| 300| 2| 200| 4| 400|
+---+---+---------+-----------+------------------+-------+--------------+
所有这些DF上的内部联接导致"之前的"和" next"两侧。但是,如果您只想查看上一个或下一个记录,则可以执行逐个连接。