使用:PostgreSQL 10.5
这个问题有点类似于:
PostgreSQL Get a random datetime/timestamp between two datetime/timestamp
answer given by @pozs解决了这个问题但不允许我约束返回的随机时间戳内的小时数。我想说这是对这个问题的延伸。
任务
不同之处在于我需要在两个时间戳之间获得一个随机时间戳,但输出值中的小时必须介于10:00:00
和18:00:00
之间。
我的尝试
我一直在尝试有效地做到这一点,但是现在只想出了存储不同部分的想法:日期,时间和毫秒,然后使用ORDER BY random() LIMIT 1
将它们与3个选择相结合。然而,这远非一个快速的解决方案。
tmp_data
持有日期,tmp_time
持有时间,tmp_ms
持有miliseconds,我使用函数加在一起以获得正确的输出:
(SELECT data FROM tmp_data ORDER BY random() LIMIT 1)
+ (SELECT czas FROM tmp_time WHERE czas BETWEEN '10:00:00' AND '18:00:00' ORDER BY random() LIMIT 1)
+ (SELECT ms FROM tmp_ms ORDER BY random() LIMIT 1)
这是完成的工作,但需要一些时间,因为有3个选择预先计算的表和排序(并且需要为每一行计算)。
样本数据/说明
给定时间限制:
2016-01-01 10:00:00
2017-12-31 18:00:00
让我们根据每个部分生成随机时间戳,但是小时(小时必须在10到18之间)。
样本输出 - 随机生成
2016-09-12 11:54:59.4919
2016-01-10 10:39:03.626985
2016-01-03 15:58:19.599016
2016-04-11 10:05:07.527829
2016-07-04 12:57:33.125333
2017-12-15 14:17:46.975731
2016-10-04 16:55:01.701048
2016-09-26 13:36:59.71145
2017-09-06 17:25:09.426963
2016-09-08 17:08:00.917743
这里的每小时都在10到18之间,但时间戳的每个其他部分都是随机的。
将输出从this answer转换为date
类型,然后添加10:00:00
时间(较低小时约束)和random
间隔最多8小时(小时上限约束)这样做非常快:
select
date (timestamp '2016-01-01' +
random() * (timestamp '2017-12-31' - timestamp '2016-01-01'))
+ time '10:00:00'
+ random() * INTERVAL '8 hours';
如果使用EXTRACT(epoch FROM <YOUR TIMESTAMP>)
将时间戳转换为秒,则可以执行以下操作:
random()
给出0到1
之间的值to_timestamp
将秒数转换回Postgres时间戳查询
WITH timestamps AS (
SELECT
EXTRACT(epoch FROM start::time) start_time,
EXTRACT(epoch FROM "end"::time) end_time,
EXTRACT(epoch FROM start::date) start_date,
EXTRACT(epoch FROM "end"::date) end_date
FROM (
SELECT
'2016-01-01 10:00:00'::timestamp as start,
'2017-12-31 18:00:00'::timestamp as end
) s
)
SELECT
to_timestamp(
random() * (ts.end_date - ts.start_date) + ts.start_date
)::date +
to_timestamp(
random() * (ts.end_time - ts.start_time) + ts.start_time
)::time
FROM timestamps ts