仅供参考,如果您确实使用的是 TIMESTAMP 类型,则说“时间戳的格式为 2015-06-22 18:59:59”是不正确的。此类类型有其自己的日期时间值的内部表示,自epoch 以来几乎总是计数。在您使用 Vertica 的情况下,此类存储使用 8 个字节。日期时间值的格式化发生在字符串表示生成时。切勿将字符串表示与日期时间值混淆。将两者混为一谈很可能与您的问题/困惑有关。
关于可能出现的问题的一些不同想法……
字符串字面量
您确定 Vertica 将字符串作为时间戳文字吗?您使用的格式是常见的 SQL 格式。但鉴于 Vertica 似乎是一个专门的数据库,我会仔细检查一下。
如果不允许使用字符串,您可能需要调用某种函数将字符串转换为日期时间值。
小数秒
正如Martin Smith 的评论所指出的,doc for Timestamp-related data types in Vertica 7.1 表示这些类型的分辨率可以达到microseconds 的小数秒。这意味着分数最多保留 6 位小数。
因此,如果您正在搜索“2015-06-22 18:59:59”但存储的值为“2015-06-22 18:59:59.012345”,则查询不匹配。
半开
上述小数秒问题通常是人们在处理时间跨度时遇到问题的原因。如果你天真地试图确定结束时间,你可能会遇到问题。在您的示例字符串中看到“59:59”让我觉得这适用于您。
更好的时间跨度方法是“半开放”(或Half-Closed,随便什么),其中开始是包含,而结尾是专有。常见的符号是[)。在比较逻辑中,这意味着:value >= start AND value < stop。请注意stop 比较中缺少等号。在英语中,我们会说“查找从下午 2:00 开始到下午 3:00 的一小时的发票,但不包括下午 3:00”。
半开一周是指周一至周一,一个月是一个月的第一天到下一个月的第一天,一年是一年的 1 月 1 日到下一年的 1 月 1 日。
p>
半开意味着不在 SQL 中使用BETWEEN。 SQL 的BETWEEN 有often be criticized。相反,请执行以下操作来查找一个小时的发票。请注意字符串文字末尾的Z,表示“UTC 时区”(“Z”表示“Zulu”)。 (但请验证,因为我的 SQL 语法可能需要修复。)
SELECT *
FROM some_table_
WHERE invoice_received_ >= '2015-06-22 18:00:00Z'
AND invoice_received_ < '2015-06-22 19:00:00Z'
;
此查询将捕获任何值,例如 '2015-06-22 18:59:59.654321" 这似乎在逃避你。
保留字
我希望您还没有真正将您的表命名为“table”而将列命名为“timestamp”。这种关键字和保留字的使用可能会导致明显的错误或更微妙的奇怪问题。
提示:避免各种数据库中超过一千个保留字的简单方法是在结尾添加下划线。 SQL 标准明确承诺永远不会在其保留字中使用尾随下划线。所以使用“timestamp_”而不是“timestamp”。另一个例子:“invoice_”表和“received_”列。我建议在 SQL 中所有你的名字的东西上这样做:列、表、约束、索引等等。
时区
您使用的是TIMESTAMP,它是TIMESTAMP WITHOUT TIME ZONE 的缩写。或者我认为; Vertica 文档含糊不清,但这是在 Postgres doc 中看到的常见用法,甚至可能是标准 SQL。
不管怎样,TIMESTAMP WITHOUT TIME ZONE 对于大多数商业用途来说通常是错误的类型。 WITH 时区被错误命名,因此经常被误解:它意味着“关于时区”,其中包含来自 UTC 的偏移量或其他时区信息的数据输入在插入/更新操作期间被调整为 UTC . WITHOUT 类型只是忽略任何此类偏移或时区信息。
WITHOUT 类型通常只能用于日期时间的概念,而不受任何地方的约束。例如,说“今年的圣诞节从 2015 年 12 月 25 日开始”。这意味着在 任何 时区而不是特定时区。例如,显然圣诞节在巴黎比在蒙特利尔更早开始。
如果您要为发票等法律文件添加时间戳,或与跨时区的人进行预约,或在不同地区安排发货,则应使用WITH 时区类型。
回到您可能遇到的问题:测试 Vertica 或您的客户端应用程序或您的数据库驱动程序如何处理您的输入字符串。它可能会使用客户端计算机的当前默认时区来调整时区,作为字符串解析的一部分。发送到数据库时,如果在存储期间未对 UTC 进行调整,则该值将与存储的值不匹配。
提示:通常最佳做法是在 UTC 中执行所有存储和业务逻辑,仅在用户期望的地方调整到本地时区。