【问题标题】:Postgres returns different results depending on clientPostgres 根据客户端返回不同的结果
【发布时间】:2019-08-12 23:43:08
【问题描述】:

我已经为 Heroku 和 AWS Beanstalk 部署了一个应用程序。他们都使用如下所示的 SQL 查询查询同一个 Postgres 数据库实例(在 AWS RDS 中),以查询包括今天在内的过去 16 天的计数

SELECT
    d.date AS interval,
    count(ct.id) AS count
FROM (SELECT
        to_char(date_trunc('day', (CURRENT_DATE - offs)), 'YYYY-MM-DD') AS date
      FROM generate_series(0, 15) AS offs) d
   LEFT OUTER JOIN my_table ct ON d.date = to_char(date_trunc('day', ct.created_at::timestamp WITH time zone at time zone 'US/Eastern'),    'YYYY-MM-DD')
WHERE
    ct.inserted_at::bigint >= 1564200000000.0
GROUP BY
    d.date;

WHERE 子句中以毫秒为单位的纪元以编程方式派生为美国东部时区 15 天前的午夜。我已经检查过在 AWS Beanstalk 和 Heroku 上发出查询时这个值是相同的,所以它不应该是这里的因素。

Heroku 应用程序按预期为我提供了 16 行,就像我从本地计算机查询一样。但是,AWS Beantalk 服务器在没有今天的数据点的情况下返回 15 行。我觉得它必须与时区有关。我是 Postgres 的新手,通过谷歌搜索得到了这个查询。 CURRENT_DATE 在不同的机器上是否不同从而导致问题? SQL高手请帮帮我,在此先感谢!

【问题讨论】:

  • @GordonLinoff 你是什么意思,它在我的控制台中运行良好,从本地 Flask,从 Heroku 和 AWS Beanstalk 上的 Flask 应用程序运行。
  • 。 .你的格式很糟糕。我不想在这里过分评判,但很难看出子查询在哪里结束。它确实有一个适当的别名。
  • 它们是否都连接到一个数据库实例?或者你的意思是你已经在 Heroku postgres 和 AWS RDS 上加载了相同的数据库内容,所以你实际上有两个数据库实例? (可能是一个愚蠢的问题,但我对亚马逊的产品并不熟悉)。
  • 在 90% 的案例中我看到了这个问题,不同的客户端连接到不同的数据库。
  • @harmic 不,它们连接到 AWS RDS 中的同一个数据库实例。编辑问题更清楚。

标签: sql postgresql amazon-web-services


【解决方案1】:

CURRENT_DATE 取决于会话的时区。如果没有在会话级别设置,则默认为用户的默认时区,然后是数据库的默认时区,然后是集群的默认时区。

一个例子:

postgres=# set time zone 'UTC';
SET
postgres=# select current_date;
 current_date
--------------
 2019-08-12
(1 row)
postgres=# set time zone 'Australia/ACT';
SET
postgres=# select current_date;
 current_date
--------------
 2019-08-13
(1 row)

此外,根据 ct.created_at 的数据类型,这也可能受到会话时区的影响。这是一个例子:

-- A simple table with two columns, one w/o time zone and one with
postgres=# create table test (a timestamp, b timestamptz);
CREATE TABLE
postgres=# set timezone to 'UTC';
SET
postgres=# insert into test values (now(), now());
INSERT 0 1
postgres=# insert into test values (now(), now());
INSERT 0 1
postgres=# insert into test values (now(), now());
INSERT 0 1
postgres=# select a::timestamp with time zone at time zone 'US/Eastern', b::timestamp with time zone at time zone 'US/Eastern' from test;
          timezone          |          timezone
----------------------------+----------------------------
 2019-08-12 10:39:31.043397 | 2019-08-12 10:39:31.043397
 2019-08-12 10:39:32.57214  | 2019-08-12 10:39:32.57214
 2019-08-12 10:39:33.258001 | 2019-08-12 10:39:33.258001
(3 rows)

-- When the session time zone is set to UTC, these are the same
-- What happens when we change?

postgres=# set time zone 'US/Eastern';
SET
postgres=# select a::timestamp with time zone at time zone 'US/Eastern', b::timestamp with time zone at time zone 'US/Eastern' from test;
          timezone          |          timezone
----------------------------+----------------------------
 2019-08-12 14:39:31.043397 | 2019-08-12 10:39:31.043397
 2019-08-12 14:39:32.57214  | 2019-08-12 10:39:32.57214
 2019-08-12 14:39:33.258001 | 2019-08-12 10:39:33.258001
(3 rows)

不带时区的时间戳列现在与另一列相差四个小时。

因此,如果您在输出中遇到差异,可能值得在脚本中添加show time zone; 语句以查看是否存在任何差异。

【讨论】:

    猜你喜欢
    • 2013-03-31
    • 2014-07-13
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    相关资源
    最近更新 更多