首页 > 解决方案 > SparkSql 查询以从 cassandra 获取定义值的上一行和下一行

问题描述

我们必须编写一个 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

但这应该不按操作顺序执行。

标签: apache-sparkcassandraapache-spark-sql

解决方案


您可以使用 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 上的内部连接会导致“上一个”和“下一个”两侧的某些条目丢失。但是,如果您有兴趣查看前一个或下一个记录,您可以执行一个接一个的连接。


推荐阅读