Postgres:查询timestampz上的特定日期不会返回任何数据,而我可以在postgres客户端中查看数据

时间:2017-08-30 00:37:14

标签: postgresql

我是postgres的新手,在发布这里之前我一直在谷歌搜索大约1小时。

希望你可以帮我解决这个可能是微不足道的问题。

我有一个使用此架构创建的数据库LTC

CREATE TABLE LTC (
       id       SERIAL PRIMARY KEY,
       time     timestamptz,
       side     CHAR(4),
       price    REAL,
       v        REAL,
       n        INT
    );

我想查询获取time ='2017-08-12T03:58:26.563Z'的所有数据(来自javascript的ISO字符串)。我知道当时数据库中有超过一百行的数据,我在postgres客户端看到了。

这是我正在做的查询:

select * from LTC where time = '2017-08-12T03:58:26.563Z'::timestamptz

为什么我没有得到任何结果?

修改

仍然不确定为什么它不起作用,但我写了一个解决办法:

在JavaScript中:

var date    = new Date('2017-08-12T03:58:26.563Z').toISOString(); // actual time passed as parameter in my function, hard-coded for the example
var reg     = new RegExp("([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\.[0-9]*Z","gmi");
var start   = date.replace(reg, function(match,year,month,day,hour,min,sec,ms) {
    return year+'-'+month+'-'+day+'T'+hour+':'+min+':00.000Z';
});
var end     = date.replace(reg, function(match,year,month,day,hour,min,sec,ms) {
    var min = parseInt(min)+1;
    if (min<=9) {
        min = '0'+min;
    }
    return year+'-'+month+'-'+day+'T'+hour+':'+min+':00.000Z';
});

var query   = "select * from LTC where time >= '"+start+"'::timestamptz and time < '"+end+"'::timestamptz"; // This works

1 个答案:

答案 0 :(得分:1)

尝试在两者上使用date_trunc('second',timestamp)以确保数字精度不会让你失望。可能还有其他小数位,您的客户端没有显示这些小数位并失去相等性。

另一种可能的解决方案是给出范围(between x and y)以避免数字平等问题。

如果您可以获得所表示数据的精确副本(如果您熟悉的话可能使用pg_dump),我们将更容易提供帮助,以便我们可以使用您正在使用的数据进行测试。

您可能想要检查的最后一件事是明确说明您要引用的时区。我通常使用timestamp without time zone来避免此问题,但将时区自动设置为不同的值也可能会让您失望。测试的一个好方法是选择两个值,如

select *, l.time = p.ts as test
from LTC l, (select '2017-08-12T03:58:26.563Z'::timestamptz as ts) p
;

修改

我已经构建了一个测试来尝试重现您的行为:

CREATE TABLE LTC (
 id serial
 , time timestamptz
 );

 INSERT INTO LTC (time)
 values ('2017-08-12T03:58:26.56312345'::timestamptz)
 returning *;

 select *
 from LTC 
 where time = '2017-08-12T03:58:26.563Z'::timestamptz
 ;

 select *, l.time = p.ts as test
from LTC l, (select '2017-08-12T03:58:26.563Z'::timestamptz as ts) p
;

我得到的实际上是:

1;"2017-08-12 03:58:26.563123-04";"2017-08-11 23:58:26.563-04";f

希望你能看到发生了什么 - '2017-08-12T03:58:26.563Z'::timestamptz被解释为UTC时间然后转换为我的时区(UTC-04),所以被比较的实际上是一个不同的日期一共!将来,并排显示这种平等是一种很好的方法来测试你正在执行你的想法(尤其是经常发生自动转换的日期/时间)。