最近,StackOverflow用户告知我,使用BETWEEN
运算符且数据类型为timestamp without time zone
的值不应。以下是报价。
介于> =和< =之间,不得与包含时间戳的范围一起使用。
当被问及对这篇论文的解释或者Postgres文档的链接时,它说我已经得到了答案
为什么这么简单的事情需要一个带文档的网站。我相信如果你谷歌你可以找到很多(至少我在各种论坛上的详细帖子证明了这个案例)
好吧我用Google搜索了。并没有发现任何建议不要使用带有时间戳值的运算符。实际上,SO上的this answer使用它们,this mailing group post也是如此。
我被告知这些年来我做错了。真的是这样吗?
据我所知,时间戳的Postgres最大精度为1 microsecond
- 如果我错了,请纠正我。因此,下面的陈述不等同于什么?
sample_date BETWEEN x AND y::timestamp - INTERVAL '1 microsecond'
和
sample_date >= x AND sample_date < y
编辑:样本只是对差异的考虑。我知道开发人员可能会错过时间部分,但假设有人知道它的行为,为什么不能使用?一般来说,这只是一个样本,但我想知道更大的范围。我一直在调查规划器,它似乎正在解析BETWEEN
到>= AND <=
。
为什么在结果方面优先写>= AND <=
而不是BETWEEN
- 不包括翻译时间?
答案 0 :(得分:1)
使用ts BETWEEN validfrom AND validto
代替ts >= validform AND ts <= validto
绝对没有错。他们是一样的。
我只能猜测,但我会说这个警告针对的是不同的东西,即上面的(相同)条款中的任何一个是否正确使用。
现在这当然取决于你要做的事情,但很多时候这样的子句用于识别特定时间戳的一个有效行。在这种情况下,上面的子句是错误的,因为当行更改时,如果值为ts
,则会得到两个结果。
考虑一下:
CREATE TABLE names (
id integer PRIMARY KEY,
val text NOT NULL,
validfrom timestamptz NOT NULL,
validto timestamptz NOT NULL
);
INSERT INTO names VALUES (1, 'Smith', '1985-05-02 00:00:00', '2009-01-30 00:00:00');
INSERT INTO names VALUES (2, 'Jones', '2009-01-30 00:00:00', 'infinity');
这是一个历史性的人名表。
如果您使用上面的WHERE
子句来查询某个时间有效的名称,那么它将适用于
SELECT val FROM names
WHERE current_timestamp BETWEEN validfrom AND validto;
但它会为
做错事SELECT val FROM names
WHERE '2009-01-30' BETWEEN validfrom AND validto;
这是因为名称有效区间的终点是不是区间的一部分。对于这种情况,写下来是正确的:
SELECT val FROM names
WHERE '2009-01-30' >= validfrom AND '2009-01-30' < validto;