4

我们正在使用带有 timestamptz 类型的表列的 Vertica 数据库,所有数据都根据 UTC 时区插入。我们正在使用 spring-jdbc 的NamedParameterJdbcTemplate

所有查询都基于完整的日历日,例如开始日期 2013/08/01 和结束日期 2013/08/31,这会带来 '2013/08/01 00:00:00.0000' 和 '2013/08/31 23 之间的所有内容:59:59.9999'

我们正在尝试修改我们的查询以考虑时区,即我可以为我的本地时区我可以要求 '2013/08/01 00:00:00.0000 Asia/Jerusalem' 直到 '2013/08/31 23:59:59.9999 Asia /Jerusalem',与 '2013/08/01 00:00:00.0000 UTC' 到 '2013/08/31 23:59:59.9999 UTC' 明显不同。

到目前为止,我找不到这样做的方法,我尝试在会话中设置时区:

将时区设置为“亚洲/耶路撒冷”;

这甚至不适用于我的数据库客户端。

计算 Java 代码中的差异对我们不起作用,因为我们还有返回日期分组的查询(这将完全搞砸)。

有什么想法或建议吗?

4

2 回答 2

4

我不熟悉 Veritca,但有一些一般性建议:

  • 通常最好对日期范围查询使用半开间隔。开始日期应该是包含的,而结束日期应该是排除的。换句话说:

    start <= date < end
    

    或者

    start <= date && end > date
    

    您的结束日期不会是'2013/08/31 23:59:59.9999',而是第二天的开始日期,或者'2013/09/01 00:00:00.0000'。这避免了与小数精度有关的问题。

    该示例用于查找单个日期。由于您要查询一系列日期,因此您有两个输入。所以它会是:

    startFieldInDatabase >= yourStartParameter
        AND
    endFieldInDatabase < yourEndParameter
    

    同样,您将首先将 end 参数值递增到第二天的开始。

  • timestamptz鉴于您在回答中谈到了类型,听起来 Vertica 可能是 TZ 意识的。假设它们类似于Oracle 的 TIMESTAMPTZ 类型,那么听起来您的解决方案可以正常工作。

  • 但通常,如果您在数据库中以 UTC 存储时间,那么您只需提前转换查询输入时间。因此,您无需在'2013/08/01 00:00:00.0000'and之间进行查询,而是'2013/09/01 00:00:00.0000'提前将其转换并在 and 之间进行'2013/07/31 21:00:00.0000'查询'2013/08/31 21:00:00.0000'。已经有很多关于如何在 Java 中本地或使用Joda Time进行转换的帖子,所以我不会在这里重复。

  • 附带说明一下,您应该确保您使用的任何 TZDB 实现(Vertica、Java 或 JodaTime 的)都具有最新的2013d 更新,因为这包括今年生效的以色列夏令时规则的更改。

于 2013-09-02T17:53:36.157 回答
3

好吧,很明显:

将时区设置为“亚洲/耶路撒冷”;

工作了,我只是没有意识到,但为了帮助其他人,我将添加其他有效的东西:

从 my_table 中选择时区“亚洲/耶路撒冷”的字段;

将适用于 timestamptz 字段

于 2013-09-02T13:29:19.580 回答