PostgreSQL 在具有小时约束的两个时间戳之间获取随机值
PostgreSQL Get random value between two timestamps with hours constraint
使用:PostgreSQL 10.5
这个问题有点类似于:
PostgreSQL Get a random datetime/timestamp between two datetime/timestamp
answer given by @pozs 解决了问题,但不允许我限制返回的随机时间戳中的小时数。 我想说这是这个问题的扩展。
任务
不同的是我需要在两个时间戳之间得到一个random时间戳,但是输出值hour =]必须介于 10:00:00
和 18:00:00
.
之间
我的尝试
我一直在努力节省时间,但现在只想到了存储以下不同部分的想法:日期、时间和毫秒,然后使用 ORDER BY random() LIMIT 1
将它们与 3 个选择结合起来.然而,这远不是一个快速的解决方案。
tmp_data
保存日期,tmp_time
保存时间,tmp_ms
保存毫秒,我使用函数将它们加在一起以获得正确的输出:
(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 次选择了带有排序的预计算表(并且需要为每一行计算)。
样本数据/解释
鉴于时间限制:
- start_timestamp =>
2016-01-01 10:00:00
- end_timestamp =>
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 点之间,但时间戳的其他部分是随机的。
如果您使用 EXTRACT(epoch FROM <YOUR TIMESTAMP>)
将时间戳转换为秒,您可以这样做:
random()
给出一个介于 0 和 1
之间的值
- 如果将随机值乘以时间戳差异,您将得到可能的范围(对于 10 到 18 小时,范围将在 0 到 8 小时之间)
- 将起点添加到范围会将计算值移动到起点和终点之间的值。现在你有了预期的随机时间戳(以秒为单位)
- 使用
to_timestamp
将秒数转换回 Postgres 时间戳
- 这样做 2 次:一次获取随机日期,一次获取随机时间。
- 添加两个时间戳(一个转换为日期,一个转换为时间)。
查询
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
将输出从 this answer 转换为 date
类型,然后添加 10:00:00
时间(下小时约束)和 random
最多 8 小时的间隔(上小时) constraint)做的很快:
select
date (timestamp '2016-01-01' +
random() * (timestamp '2017-12-31' - timestamp '2016-01-01'))
+ time '10:00:00'
+ random() * INTERVAL '8 hours';
使用:PostgreSQL 10.5
这个问题有点类似于:
PostgreSQL Get a random datetime/timestamp between two datetime/timestamp
answer given by @pozs 解决了问题,但不允许我限制返回的随机时间戳中的小时数。 我想说这是这个问题的扩展。
任务
不同的是我需要在两个时间戳之间得到一个random时间戳,但是输出值hour =]必须介于 10:00:00
和 18:00:00
.
我的尝试
我一直在努力节省时间,但现在只想到了存储以下不同部分的想法:日期、时间和毫秒,然后使用 ORDER BY random() LIMIT 1
将它们与 3 个选择结合起来.然而,这远不是一个快速的解决方案。
tmp_data
保存日期,tmp_time
保存时间,tmp_ms
保存毫秒,我使用函数将它们加在一起以获得正确的输出:
(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 次选择了带有排序的预计算表(并且需要为每一行计算)。
样本数据/解释
鉴于时间限制:
- start_timestamp =>
2016-01-01 10:00:00
- end_timestamp =>
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 点之间,但时间戳的其他部分是随机的。
如果您使用 EXTRACT(epoch FROM <YOUR TIMESTAMP>)
将时间戳转换为秒,您可以这样做:
random()
给出一个介于 0 和1
之间的值
- 如果将随机值乘以时间戳差异,您将得到可能的范围(对于 10 到 18 小时,范围将在 0 到 8 小时之间)
- 将起点添加到范围会将计算值移动到起点和终点之间的值。现在你有了预期的随机时间戳(以秒为单位)
- 使用
to_timestamp
将秒数转换回 Postgres 时间戳
- 这样做 2 次:一次获取随机日期,一次获取随机时间。
- 添加两个时间戳(一个转换为日期,一个转换为时间)。
查询
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
将输出从 this answer 转换为 date
类型,然后添加 10:00:00
时间(下小时约束)和 random
最多 8 小时的间隔(上小时) constraint)做的很快:
select
date (timestamp '2016-01-01' +
random() * (timestamp '2017-12-31' - timestamp '2016-01-01'))
+ time '10:00:00'
+ random() * INTERVAL '8 hours';