简体   繁体   English

如何将时间戳从一个范围缩放到另一范围?

[英]How to scale timestamp from one range to another range?

I've got table with timestamps of item changes: 我有带有项目更改时间戳的表:

  • ID: INT ID:INT
  • item: INT - foreign key 项目:INT-外键
  • created: TIMESTAMP 创建时间:TIMESTAMP

I need for certain item to squeeze created timestamps to some range. 我需要某些项目将创建的时间戳压缩到某个范围。 Ie.: 即:

  • src range: 1.10.2015 00:00 - 4.10.2015 23:59 src范围:1.10.2015 00:00-4.10.2015 23:59
  • dst range: 1.10.2015 00:00 - 1.10.2015 23:59 dst范围:1.10.2015 00:00-1.10.2015 23:59
  • so, sample TIMESTAMP would look like: 因此,示例TIMESTAMP如下所示:
    • 2.10.2015 00:00 -> 1.10.2015 6:00 2.10.2015 00:00-> 1.10.2015 6:00
    • 3.10.2015 00:00 -> 1.10.2015 12:00 3.10.2015 00:00-> 1.10.2015 12:00
    • 4.10.2015 00:00 -> 1.10.2015 18:00 2015年10月4日00:00-> 2015年10月1日18:00
    • 4.10.2015 12:00 -> 1.10.2015 21:00 2015年10月4日12:00-> 2015年10月1日21:00

I need to keep year, month, day, hour, minute, seconds part of resulting timestamp. 我需要保留生成的时间戳的年,月,日,时,分,秒部分。 Must not round seconds/minutes to zeroes. 不得将秒/分钟取整为零。

Scale precision doesn't matter much, but order of changes by created timestamp must be kept same as it was before scaling . 缩放精度无关紧要,但是通过创建的时间戳进行的更改顺序必须保持与缩放之前相同 I don't care much about other scaling details: whether it's start/final time, inclusive/exclusive, or whether it scales to range of 6:00/5:59 hours. 我不太在乎其他缩放细节:是开始/结束时间,包含时间/排除时间,还是缩放至6:00/5:59小时。

I can do it with some external application that would transform it on its own, then updates timestamps. 我可以使用一些外部应用程序来完成此任务,该应用程序可以自行对其进行转换,然后更新时间戳。 However, I now need to do it using SQL only. 但是,我现在只需要使用SQL即可。 Is it possible? 可能吗? It may be postgres specific. 它可能是特定于postgres的。

You may assume, there won't be collision after scaling applies. 您可能会假设在应用缩放后不会发生冲突。

something like this? 这样的东西?

select id, item, (' ['||created||', '||created_l- '00:00.000001'::time||') ' )::tsrange as some_range from (
select id, item, created  , lead(created) over(order by created)  created_l from my_table  order by created) q1
with r (src, dst) as ( values
    (
        tsrange('2015-10-01', '2015-10-05', '[)'),
        tsrange('2015-10-01', '2015-10-02', '[)')
    ),
    (
        tsrange('2015-10-06', '2015-10-10', '[)'),
        tsrange('2015-10-02', '2015-10-03', '[)')
    )
), t (id, src) as ( values
    (1,'2015-10-02 00:00'::timestamp),
    (2,'2015-10-03 00:00'),
    (3,'2015-10-04 00:00'),
    (4,'2015-10-04 12:00'),
    (5,'2015-10-06 11:00'),
    (6,'2015-10-07 15:00')
)
select
    t.id, t.src,
    lower(r.dst) + rank() over(
            partition by r.dst order by t.src
    ) * interval '1 second' as squeezed
from
    t
    inner join
    r on t.src <@ r.src
;
 id |         src         |      squeezed       
----+---------------------+---------------------
  1 | 2015-10-02 00:00:00 | 2015-10-01 00:00:01
  2 | 2015-10-03 00:00:00 | 2015-10-01 00:00:02
  3 | 2015-10-04 00:00:00 | 2015-10-01 00:00:03
  4 | 2015-10-04 12:00:00 | 2015-10-01 00:00:04
  5 | 2015-10-06 11:00:00 | 2015-10-02 00:00:01
  6 | 2015-10-07 15:00:00 | 2015-10-02 00:00:02

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM