PostgreSQL-创建秒视图

时间:2018-09-07 10:34:30

标签: sql postgresql time

我有一个名为tb_records的表,该表记录了发生的情况。样本值为:

id  from        to
1   01:00:00    01:00:03
2   01:00:05    01:00:07
3   01:00:50    01:00:51

我想做的是在PostgreSQL中生成第二个序列。因此结果将是

id  from        to          time
1   01:00:00    01:00:03    01:00:00
1   01:00:00    01:00:03    01:00:01
1   01:00:00    01:00:03    01:00:02
1   01:00:00    01:00:03    01:00:03
2   01:00:05    01:00:07    01:00:05
2   01:00:05    01:00:07    01:00:06
2   01:00:05    01:00:07    01:00:07
3   01:00:50    01:00:51    01:00:50
3   01:00:50    01:00:51    01:00:51

通常,在Python或R中,我会选择 basic 算法(不使用任何库或程序包):

  1. 计算每个iddiff)的时间差,以秒为单位
  2. 对于每个ID,请按diff
  3. 复制行
  4. 使用初始值创建列time的列from
  5. 对于每个id和每一行,将列time增加一秒钟

由于我习惯于按顺序创建这些步骤,因此我对如何在SQL中执行操作感到困惑。

2 个答案:

答案 0 :(得分:2)

select id, "from", "to",
generate_series(('2000-01-01 '||"from")::timestamp, ('2000-01-01 '||"to")::timestamp, '1 second'::interval)::time as res
from tb_records
order by id, res 

generate_series()不适用于time类型,因此我将time转换为timestamp,然后从生成的结果中提取time部分。

SQL Fiddle Demo

答案 1 :(得分:1)

使用日历表并将其加入。 (我将列重命名;“ to”,“ from”和“ time”在SQL中都是保留字)


df1 <- data.frame(Date = as.Date(c("2013-11-01", "2014-02-01", "2014-05-01", "2014-08-01", "2014-11-01", "2015-02-01", "2015-05-01", "2015-08-01", "2015-11-01", "2016-02-01", "2016-05-01", "2016-08-01", "2016-11-01", "2017-02-01", "2017-05-01", "2017-08-01", "2017-11-01", "2018-02-01", "2018-05-01", "2018-08-01")),
                  Dividend = c(0.08, 0.10, 0.10, 0.10, 0.10, 0.11, 0.00, 0.11, 0.11, 0.13, 0.13, 0.13, 0.13, 0.14, 0.14, 0.00, 0.16, 0.15, 0.15, 0.15))

# data in xts form since quantmod is being used.
my_xts <- xts(df1$Dividend, order.by = df1$Date)

annual_data <- apply.yearly(my_xts, function(x) as.matrix(data.frame(sum(x), length(x)))  )
names(annual_data) <- c("total_divs", "no_divs")

# filter data to include only maximum dividens
annual_data[annual_data$no_divs == max(annual_data$no_divs)]

           total_divs no_divs
2014-11-01       0.40       4
2015-11-01       0.33       4
2016-11-01       0.52       4
2017-11-01       0.44       4

或使用递归CTE:


WITH omg AS ( -- calendar table
        SELECT generate_series( min(tfrom),max(tto),'1sec'::interval) AS ttick
                 FROM fromto t
        )
SELECT t.id, t.tfrom, t.tto
        , o.ttick
FROM fromto t
JOIN omg o -- join it with actual table
        ON t.tfrom <= o.ttick
        AND t.tto >= o.ttick
ORDER BY o.ttick
        ;