Postgres可以使用date_trunc函数对时间戳进行舍入(截断),如下所示:
date_trunc('hour', val)
date_trunc('minute', val)
我正在寻找一种方法将时间戳截断到最接近的5分钟边界,例如,14:26:57变为14:25:00。直截了当的方式就是这样:
date_trunc('hour', val) + date_part('minute', val)::int / 5 * interval '5 min'
由于这是查询中性能至关重要的部分,我想知道这是否是最快的解决方案,或者是否有一些我忽略的快捷方式(与Postgres 8.1+兼容)。
答案 0 :(得分:14)
我认为没有更快的方法。
我认为你不应该担心表达的表现。
执行(SELECT,UPDATE,...)语句所涉及的其他所有内容(例如,检索行的I / O)可能比日期/时间计算要贵得多。
答案 1 :(得分:8)
我想知道同样的事情。我找到了两种替代方法,但你提出的方法更快。
我非正式地对照了一个较大的表格。我将查询限制在前400万行。我在两个查询之间进行了交替,以避免因db缓存而给予一个不公平的优势。
SELECT to_timestamp(
(EXTRACT(epoch FROM ht.time) / EXTRACT(epoch FROM interval '5 min'))::int
* EXTRACT(epoch FROM interval '5 min')
) FROM huge_table AS ht LIMIT 4000000
(注意这会产生timestamptz
,即使你使用了时区unaware数据类型)
<强>结果
SELECT
date_trunc('hour', ht.time)
+ date_part('minute', ht.time)::int / 5 * interval '5 min'
FROM huge_table AS ht LIMIT 4000000
<强>结果
<强>系统强>
您的版本似乎更快。但对于我的具体用例来说还不够快。不必指定小时的优点使得epoch版本更加通用并且在客户端代码中产生更简单的参数化。它处理2 hour
间隔以及5 minute
间隔,而不必将date_trunc
时间单位参数提升。最后,我希望将时间单位参数更改为时间间隔参数。
答案 2 :(得分:0)
完全查询那些想知道的人(基于@DNS问题):
假设您有订单,并且您希望通过5分钟和shop_id来计算它们:
SELECT date_trunc('hour', created_at) + date_part('minute', created_at)::int / 5 * interval '5 min' AS minute
, shop_id, count(id) as orders_count
FROM orders
GROUP BY 1, shop_id
ORDER BY 1 ASC