Jac*_*ski 4 apache-spark apache-spark-sql
我一直在回顾有关StackOverflow上的array_contains(和isin)方法的问题和答案,我仍然无法回答以下问题:
为什么array_contains在SQL中接受列(引用)作为参数,而标准函数却没有?
我可以理解上述问题很容易被标记为"主要基于意见"或类似问题,所以让我将其改为以下内容:
如何使用array_contains标准函数,以便它接受来自列的参数(值)?
scala> spark.version
res0: String = 2.3.0
val codes = Seq(
(Seq(1, 2, 3), 2),
(Seq(1), 1),
(Seq.empty[Int], 1),
(Seq(2, 4, 6), 0)).toDF("codes", "cd")
scala> codes.show
+---------+---+
| codes| cd|
+---------+---+
|[1, 2, 3]| 2|
| [1]| 1|
| []| 1|
|[2, 4, 6]| 0|
+---------+---+
// array_contains in SQL mode works with arguments being columns
val q = codes.where("array_contains(codes, cd)")
scala> q.show
+---------+---+
| codes| cd|
+---------+---+
|[1, 2, 3]| 2|
| [1]| 1|
+---------+---+
// array_contains standard function with Columns does NOT work. Why?!
// How to change it so it would work (without reverting to SQL expr)?
scala> val q = codes.where(array_contains($"codes", $"cd"))
java.lang.RuntimeException: Unsupported literal type class org.apache.spark.sql.ColumnName cd
at org.apache.spark.sql.catalyst.expressions.Literal$.apply(literals.scala:77)
at org.apache.spark.sql.functions$.array_contains(functions.scala:2988)
... 49 elided
Run Code Online (Sandbox Code Playgroud)
小智 5
仅仅因为没有人关心实施(Column, Column) => Column变体.如果您检查源,您将看到设计中没有任何内容禁止您创建一个,因为标准工作流程是将非Column参数转换为文字.
它甚至没有特别的独特性.还有其他函数没有包装器进行额外的Column参数,包括但不限于不同的日期/时间处理函数和数学函数.
由于底层函数exprArrayContains确实需要争论,因此您总是可以作弊。
scala> codes.where(new Column(ArrayContains($"codes".expr, $"cd".expr))).show
+---------+---+
| codes| cd|
+---------+---+
|[1, 2, 3]| 2|
| [1]| 1|
+---------+---+
**/
Run Code Online (Sandbox Code Playgroud)
正如 user9812147 所说,这里的问题只是 SQL Parser 能够ArrayContains直接访问该函数。虽然直接函数调用似乎强制将“值”部分视为文字。
| 归档时间: |
|
| 查看次数: |
600 次 |
| 最近记录: |