SparkSQL 时间戳查询失败

Posted

技术标签:

【中文标题】SparkSQL 时间戳查询失败【英文标题】:SparkSQL Timestamp query failure 【发布时间】:2014-11-21 20:15:02 【问题描述】:

我通过 Spark 将一些日志文件放入 sql 表中,我的架构如下所示:

|-- timestamp: timestamp (nullable = true) 
|-- c_ip: string (nullable = true) 
|-- cs_username: string (nullable = true) 
|-- s_ip: string (nullable = true) 
|-- s_port: string (nullable = true) 
|-- cs_method: string (nullable = true) 
|-- cs_uri_stem: string (nullable = true) 
|-- cs_query: string (nullable = true) 
|-- sc_status: integer (nullable = false) 
|-- sc_bytes: integer (nullable = false) 
|-- cs_bytes: integer (nullable = false) 
|-- time_taken: integer (nullable = false) 
|-- User_Agent: string (nullable = true) 
|-- Referrer: string (nullable = true) 

如您所见,我创建了一个时间戳字段,我读到的 Spark 支持该字段(据我了解,日期不起作用)。我很想使用像“where timestamp>(2012-10-08 16:10:36.0)”这样的查询,但是当我运行它时,我不断收到错误。 我尝试了以下两种 sintax 形式: 对于第二个我解析一个字符串,所以我确定我实际上以时间戳格式传递它。 我使用 2 个函数:parsedate2timestamp

关于我应该如何处理时间戳值的任何提示?

谢谢!

1) scala> sqlContext.sql("SELECT * FROM Logs as l where l.timestamp=(2012-10-08 16:10:36.0)").collect

java.lang.RuntimeException: [1.55] failure: ``)'' expected but 16 found 

SELECT * FROM Logs as l where l.timestamp=(2012-10-08 16:10:36.0) 
                                                  ^ 

2) sqlContext.sql("SELECT * FROM Logs as l where l.timestamp="+date2timestamp(formatTime3.parse("2012-10-08 16:10:36.0"))).collect

java.lang.RuntimeException: [1.54] failure: ``UNION'' expected but 16 found 

SELECT * FROM Logs as l where l.timestamp=2012-10-08 16:10:36.0 
                                                 ^ 

【问题讨论】:

【参考方案1】:

我认为问题首先在于时间戳的精度,而且我传递的表示时间戳的字符串必须转换为 String

所以这个查询现在可以工作了:

sqlContext.sql("SELECT * FROM Logs as l where cast(l.timestampLog as String) <= '2012-10-08 16:10:36'")

【讨论】:

【参考方案2】:

您忘记了引号。

试试这个语法:

L.timestamp = '2012-07-16 00:00:00'

或者,试试

L.timestamp = CAST('2012-07-16 00:00:00' AS TIMESTAMP)

【讨论】:

我已经尝试在时间戳周围加上单引号,它看起来不像时间戳那样读取它,因为结果集是空的,它不应该。我也尝试了 CAST AS 建议,但它也不起作用。我特别收到这个错误:java.lang.RuntimeException: [1.76] failure: ``STRING'' expected but identifier TIMESTAMP found 值得注意的是,对于未来的读者来说,这已经很老了。时间戳数据具有毫秒(或更好)的精度。仅仅因为显示是第二精度并不意味着支持数据是 - 它实际上是四舍五入的。使用相等运算符时,您必须完全匹配。对于真实世界的数据,这很难。使用有界时间表达式,例如“between”来扫描时间范围。【参考方案3】:

将时间戳的字符串表示形式转换为时间戳。 cast('2012-10-10 12:00:00' as timestamp) 然后你可以将比较作为时间戳,而不是字符串。而不是:

sqlContext.sql("SELECT * FROM Logs as l where cast(l.timestamp as String) <= '2012-10-08 16:10:36'")

试试

sqlContext.sql("SELECT * FROM Logs as l where l.timestamp <= cast('2012-10-08 16:10:36' as timestamp)")

【讨论】:

【参考方案4】:

遗憾的是,这对我不起作用。我正在使用 Apache Spark 1.4.1。以下代码是我的解决方案:

Date date = new Date();

String query = "SELECT * FROM Logs as l where l.timestampLog <= CAST('" + new java.sql.Timestamp(date.getTime()) + "' as TIMESTAMP)";

sqlContext.sql(query);

将 timestampLog 转换为字符串不会引发任何错误,但不会返回任何数据。

【讨论】:

以上是关于SparkSQL 时间戳查询失败的主要内容,如果未能解决你的问题,请参考以下文章

Spark SQL 查询以获取在 AWS S3 中存储为 CSV 的 Athena 表的最后更新时间戳

SparkSQL - 两个时间戳之间的差异(以分钟为单位)

Hive/SparkSQL:如何将 Unix 时间戳转换为时间戳(不是字符串)?

如何将镶木地板文件的 int64 数据类型列转换为 SparkSQL 数据框中的时间戳?

Spark SQL:无需秒即可解析时间戳

Spark - HiveContext |错误的时间戳(减去 4 小时)