如何在spark数据框中只获得一个小于指定值的行

时间:2018-04-27 17:32:35

标签: scala apache-spark pyspark

我有一个如下的数据框 -

Id,timestamp
100,1
200,2
300,3
400,4
500,5
600,6

现在我想只得到一行,其值小于时间戳5。 等效的SQL查询:select * from table1 where id <5 order by timestamp desc limit 1.

但是在spark查询中我不想按操作执行顺序,因为我们的数据量太大,所以需要花费太多时间。 如果不使用订单,是否可以在spark中执行相同操作?

5 个答案:

答案 0 :(得分:1)

首先,您可以在spark中运行该SQL查询:

dataframe.createOrReplaceTempView("table1")

spark.sql("select * from table1 where id <5 order by timestamp desc limit 1")

除此之外,您知道id(我认为您的意思是timestamp)恰好是4:

dataframe.where("timestamp = 4")

答案 1 :(得分:1)

虽然其他答案是正确的(您可以直接在临时视图或orderBy + limit上使用您的查询),但似乎无法解决您的主要问题:

  

但是在Spark查询中我不想按操作执行顺序,因为我们的数据量太大,所以需要花费太多时间。 Spark中是否可以在不使用order by的情况下执行相同操作?

让我们来看看幕后发生的事情:

df = spark.createDataFrame(
    [(100, 1), (200, 2), (300, 3), (400, 4), (500, 5), (600, 6)],
    ("id", "timestamp"))

df.filter("timestamp < 5").orderBy(df["timestamp"].desc()).limit(1).explain()
# == Physical Plan ==
# TakeOrderedAndProject(limit=1, orderBy=[timestamp#35L DESC NULLS LAST], output=[id#34L,timestamp#35L])
# +- *(1) Filter (isnotnull(timestamp#35L) && (timestamp#35L < 5))
#    +- Scan ExistingRDD[id#34L,timestamp#35L]

正如你所看到的,根本没有任何排序。 Spark分析了计划,代替完全排序,应用了TakeOrderedAndProject。结果,每个分区只记录最高记录。

操作在行数方面是线性的,但您不必担心排序所有记录所需的全部随机播放。

结论?只要极限值很小,就没有什么可担心的了(有很大的限制,事情可能会变得难看)。

答案 2 :(得分:0)

简而言之:排序,按值过滤&lt;指定,选择结果的最后一个元素。

答案 3 :(得分:0)

另一种方式:

import pyspark.sql.functions as f
df.filter("id<5").orderBy(f.col("timestamp").desc()).first()

答案 4 :(得分:0)

如果由于数据帧大小而要避免ordering,请考虑使用reduce仅在过滤后获得最大值:

val df = Seq(
  (100, 1),
  (200, 2),
  (300, 3),
  (400, 4),
  (500, 5),
  (600, 6)
).toDF("id", "ts")

df.where($"ts" < 5).reduce( (acc, r) =>
  if (r.getAs[Int]("ts") > acc.getAs[Int]("ts")) r else acc
)
// res1: org.apache.spark.sql.Row = [400,4]