fly*_*r88 5 postgresql timestamp
我有一张名为accounts. 我有兴趣检索状态超过 10 天未更新的那些帐户。我想过这个查询,它似乎有效,但我不确定这是最好的方法:
SELECT * from accounts
WHERE status = 'PENDING_PAYMENT'
AND (date_part('day', (now() - status_updated_at)) > 10);
Run Code Online (Sandbox Code Playgroud)
我不喜欢这个now()部分的一件事是。如果now()不是为每个记录计算而是在开始时计算单个时间戳值,那将是理想的。此外,我希望这个例子返回1:
假设对于一条记录,该status_updated_at列具有以下值:2015-10-05 23:00:00。并now()返回2015-10-06 01:00:00。尽管只有几个小时的差异,但我希望结果是1.
Erw*_*ter 11
您可以使用该函数age()来简化您的表达式(返回interval)。但是开始时使用sargable表达式效率更高。
这以确切的时差运行(当前时间是相关的):
SELECT *
FROM accounts
WHERE status = 'PENDING_PAYMENT'
AND status_updated_at < now() - interval '10 days'
Run Code Online (Sandbox Code Playgroud)
要在整个日历日内运行(直到但不包括本地时区午夜):
...
AND status_updated_at < CURRENT_DATE - 10
Run Code Online (Sandbox Code Playgroud)
你可以只减去integer从date,结果仍然是date可以直接比较的数据类型timestamp的列。
您似乎在询问第二个变体的行为。所不同的是更超过10天。
回复您的评论。
CURRENT_DATE是一个返回 a 的特殊函数date(('now'::cstring)::date在 pg 9.4 中内部实现)。运算符有多种变体-。我pg_operator在当前测试数据库的系统目录中找到了 43 。通过操作数的数据类型选择正确的。
对于date - integer,integer天数从date- 中减去,只是因为它是这样定义的。这是有道理的我来说,单元的date是“天”。现代 Postgres 在integer内部将日期和时间戳存储为数字。这是非常便宜的变换相互转化,并/减去天是很便宜添加到/从date和它的也很便宜对它们进行比较。
表达式的结果是 a date,而 whilestatus_updated_at是一timestamp列。我首先假设一个隐式赋值转换,但该步骤甚至不是必需的,date并且timestamp共享二进制兼容格式并且可以直接进行比较。有<注册的运营商变体timestamp < date。列值可以“按原样”进行测试,表达式是 sargable,可以使用 btree 索引。
SELECT oprname, oprleft::regtype, oprright::regtype
FROM pg_operator
WHERE oprname = '<'
AND oprleft = 'timestamp'::regtype;
Run Code Online (Sandbox Code Playgroud)
有关的:
使用timestamptz,时区的问题将被添加到等式中,这很复杂,但通常会分解为非常简单的评估:
now()如果
now()不是为每个记录计算而是在开始时计算单个时间戳值,那将是理想的。
你的愿望已经实现。所述now()的功能(包括家庭CURRENT_DATEID来定义STABLE,即,now()返回在同一事务中相同的值。
| 归档时间: |
|
| 查看次数: |
14609 次 |
| 最近记录: |