在 postresql 服务器 9.1.4 上的 OSX 10.8 是一个意外行为。因为在 Ubuntu 12.04 上它是正确的。
要重现此问题,请使用以下 postgres sql 示例数据库。注意:时间戳值是在时区“欧洲/柏林”中选择的,时间戳是在2012 年DST 结束时进行的,本次测试就是这种情况。
BEGIN;
DROP TABLE data;
CREATE TABLE data (
"id" int8 NOT NULL,
"timestampwithtimezone" timestamp(6) WITH TIME ZONE,
CONSTRAINT "data_pkey" PRIMARY KEY ("id")
);
COMMIT;
BEGIN;
INSERT INTO data (id, timestampwithtimezone) VALUES (205,'2012-10-28 01:30:00+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (204,'2012-10-28 02:00:00+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (203,'2012-10-28 02:30:00+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (202,'2012-10-28 02:59:59+02');
INSERT INTO data (id, timestampwithtimezone) VALUES (106,'2012-10-28 02:00:00+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (107,'2012-10-28 02:30:00+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (108,'2012-10-28 02:59:59+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (109,'2012-10-28 03:00:00+01');
INSERT INTO data (id, timestampwithtimezone) VALUES (110,'2012-10-28 03:30:00+01');
COMMIT;
如果我键入以下 SQL 查询,它只查找给定时间戳之前的最后一个存在的时间戳:
SELECT id, timestampwithtimezone at time zone 'Europe/Berlin' as timestampwithtimezone
FROM data
WHERE
timestampwithtimezone at time zone 'Europe/Berlin'
< cast('2012-10-28T02:30:00.000+01' AS timestamp)
ORDER BY timestampwithtimezone DESC
LIMIT 1;
我的预期结果是:
║ 106 ║ 2012-10-28 02:00:00 ║</p>
因为我想要给定 (2012-10-28T02:30:00.000+01) 时间戳之前的最后一个时间戳。但结果包含:
║ 204 ║ 2012-10-28 02:00:00 ║</p>
在这种情况下,postgresqls 排序似乎是错误的。在 Ubuntu 下,我得到了正确的答案,即 id: 106 而不是 204。
但:
如果我设置了这个查询:(唯一的区别是我将结果集映射到时区):
SELECT id, timestampwithtimezone
FROM data
WHERE timestampwithtimezone at time zone 'Europe/Berlin'
< cast('2012-10-28T02:30:00.000+01' AS timestamp)
ORDER BY timestampwithtimezone DESC
LIMIT 1;
OSX 10.8 和 Ubuntu 12.04 中的结果集与预期的一样:
║ 106 ║ 2012-10-28 02:00:00+01 ║</p>
为什么操作系统版本之间存在差异?在这种情况下,此查询的答案“204”确实是错误的。但是,如果我将时间戳映射到时区,为什么结果集会有所不同?据我所知,postgresql 在内部使用 UTC 来存储时间戳。所以 DST 在时间线上应该不是问题。为什么会发生这种情况?
提前感谢,希望得到回应。