Postegres:使用INTERVAL操作的查询不会超出约束条件

时间:2015-05-29 16:52:16

标签: postgresql timestamp intervals

就简化问题而言,我有以下疑问:

SELECT * FROM table WHERE (DATE_TRUNC('day',create_time ) > now() - interval '2 days');

运行解释我得到了这个:

->  Seq Scan on table  (cost=0.00..1.62 rows=10 width=232)
               Filter: (date_trunc('day'::text, create_time) > (now() - '2 days'::**interval**))

正如我所强调的那样,此操作(现在() - 间隔' 2天')会返回一个间隔,但我需要它作为时间戳。

在这种情况下,我如何从间隔转换为时间戳或类似的东西?

  

谢谢大家的答案,但我认为解释不是很好,   这是详细的问题:

出于性能目的,我们在这里有一个名为' transactions'每天的子表格,例如" transactions_2015_05_29'。

在每个子表上,我们有以下约束:

CONSTRAINT transactions_2015_05_29_create_time_check CHECK (date_trunc('day'::text, create_time) = '2015-05-29 00:00:00'::timestamp without time zone)

当我们执行以下操作时,请说明'我们得到以下查询:

说明:

explain SELECT * FROM pp_transactions WHERE (DATE_TRUNC('day', create_row_time) < current_date + interval '1 day');

"Result  (cost=0.00..120.52 rows=731 width=232)"
"  ->  Append  (cost=0.00..120.52 rows=731 width=232)"
"        ->  Seq Scan on transactions  (cost=0.00..1.70 rows=10 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < (('now'::text)::date + '1 day'::interval))"
"        ->  Seq Scan on **transactions_2015_05_28** pp_transactions  (cost=0.00..14.65 rows=103 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < '2015-05-30 00:00:00'::timestamp without time zone)"
"        ->  Seq Scan on **transactions_2015_05_29** transactions  (cost=0.00..16.98 rows=103 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < (('now'::text)::date + '1 day'::interval))"
"        ->  Seq Scan on **transactions_2015_05_30** transactions  (cost=0.00..16.98 rows=103 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < (('now'::text)::date + '1 day'::interval))"
"        ->  Seq Scan on **transactions_2015_05_31** transactions  (cost=0.00..16.98 rows=103 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < (('now'::text)::date + '1 day'::interval))"

正如您所看到的,有些桌子不应该存在。 但是如果我们运行以下查询,我会在explain上得到正确的结果:

说明:

explain select * FROM pp_transactions WHERE (DATE_TRUNC('day', create_row_time) < '2015-05-30 00:00:00');

"Result  (cost=0.00..30.76 rows=216 width=232)"
"  ->  Append  (cost=0.00..30.76 rows=216 width=232)"
"        ->  Seq Scan on transactions  (cost=0.00..1.46 rows=10 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < '2015-05-30 00:00:00'::timestamp without time zone)"
"        ->  Seq Scan on **transactions_2015_05_28** pp_transactions  (cost=0.00..14.65 rows=103 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < '2015-05-30 00:00:00'::timestamp without time zone)"
"        ->  Seq Scan on **transactions_2015_05_29** pp_transactions  (cost=0.00..14.65 rows=103 width=232)"
"              Filter: (date_trunc('day'::text, create_time) < '2015-05-30 00:00:00'::timestamp without time zone)"

因此,第一个查询必须表现为第二个查询。

2 个答案:

答案 0 :(得分:1)

来自postgres manual

  
      
  1. 您可以向TIMESTAMP添加或减去INTERVAL以生成另一个TIMESTAMP
  2.          TIMESTAMP'1999-12-11'+ INTERVAL'19 days'= TIMESTAMP'1999-12-30'

这对我来说是个约会(2天前在CEST 19:08),并根据手册(再次)now()生成时间戳:

 (now() - '2 days'::**interval**)

now()是一个函数,间隔是“2天”。

答案 1 :(得分:0)

理论推理为什么没有DB供应商提供的官方转换(与您的问题的标题相关):

转换此类不兼容类型的唯一方法是引入固定(但任意)的开始时间戳,在其上添加间隔(更好地说持续时间)并确定最终时间戳,然后是结果。请注意,由于时区效应(夏令时),转换可能取决于开始时间戳的选择,因为一天并不总是24小时。

然而,放弃这种奇怪的转换可能更健康。这就像比较苹果和橘子。或者在几何解释中:如何将距离转换为点?

对于PostgreSQL语句的具体分析,请同时查看PostgreSQL - documentation。我想知道为什么你认为你得到now() - interval '2 days'的结果。你能否展示你观察到的输出?但也许你没有观察到你的输出但只是对SQL-EXPLAIN的文本感到困惑,其中表达式(now() - '2 days'::**interval**)中的文本“interval”与前面的部分“2天”相关,而不是整个表达式。