在Postresql中。如何根据列中的数字值复制行

时间:2019-05-07 18:54:44

标签: postgresql

以下是问题:

Name    Start Time  End Time    Number
A1      5:13 PM     5:43 PM     0
A2      7:06 PM     8:51 PM     2
A3      6:36 PM     8:06 PM     3
A4      4:51 PM     7:51 PM     4

我想基于Number值复制行,并包括三个新列(New_Start_Time,New_End_Time和Minutes),我是Sql的新手,如何在Postresql中做到这一点?

我希望得到以下结果:

Name    Start Time  End Time    Number  New_Start_Time  New_End_Time
A1      5:13 PM     5:43 PM     0       5:13 PM         5:43 PM
A2      7:06 PM     8:51 PM     2       7:06 PM         8:00 PM
A2      7:06 PM     8:51 PM     2       8:00 PM         8:51 PM
A3      6:36 PM     8:06 PM     3       6:36 PM         7:00 PM
A3      6:36 PM     8:06 PM     3       7:00 PM         8:00 PM
A3      6:36 PM     8:06 PM     3       8:00 PM         8:06 PM
A4      4:51 PM     7:51 PM     4       4:51 PM         5:00 PM
A4      4:51 PM     7:51 PM     4       5:00 PM         6:00 PM
A4      4:51 PM     7:51 PM     4       6:00 PM         7:00 PM
A4      4:51 PM     7:51 PM     4       7:00 PM         7:51 PM

1 个答案:

答案 0 :(得分:0)

这可以使用generate_series()并计算开始时间和结束时间之间的小时数来完成。

因此,我们首先需要通过将start_time舍入为整小时来计算“基本开始时间”。这也用于添加复制行时的小时数:

with rounded as (
  select name, 
         start_time,
         end_time, 
         date_trunc('hour', start_time)::time as base_start_time,
         extract(hour from (date_trunc('hour', end_time) + interval '1 hour') - date_trunc('hour', start_time))::int as num_hours
  from times
)
select name,
       start_time, 
       end_time, 
       case 
         when h = 1 then start_time
         else base_start_time + interval '1 hour' * (h - 1)
       end as new_start_time,
       case
          when h = num_hours then end_time
          else base_start_time + interval '1 hour' * h
       end as new_end_time
from rounded
  cross join generate_series(1, num_hours, 1) as t(h)  
order by name, new_start_time;

CTE用于计算基本偏移量和需要生成的小时数。如果确定可以信任number列,则可以仅用extract(hour ...) as num_hours替换number as num_hours表达式。

然后根据该行反映的“小时”来计算新的开始和结束。对于第一个小时,我们使用现有的开始时间,对于其他所有时间,我们仅添加所需的小时数。对于新的结束时间,我们需要检查是否是最后一个小时。

以上返回:

name | start_time | end_time | new_start_time | new_end_time
-----+------------+----------+----------------+-------------
A1   | 17:13      | 17:43    | 17:13          | 17:43       
A2   | 19:06      | 20:51    | 19:06          | 20:00       
A2   | 19:06      | 20:51    | 20:00          | 20:51       
A3   | 18:36      | 20:06    | 18:36          | 19:00       
A3   | 18:36      | 20:06    | 19:00          | 20:00       
A3   | 18:36      | 20:06    | 20:00          | 20:06       
A4   | 16:51      | 19:51    | 16:51          | 17:00       
A4   | 16:51      | 19:51    | 17:00          | 18:00       
A4   | 16:51      | 19:51    | 18:00          | 19:00       
A4   | 16:51      | 19:51    | 19:00          | 19:51       

在线示例:https://rextester.com/GAZP30312