我认为您不需要生成任何行。根据您的示例数据,您可以简单地连接这两个表。
select *
from program_info pi
join usage_detail ud
on to_char(ud.start_time, 'FMday') = lower(pi.week_day)
and (pi.start_time, pi.end_time) overlaps (ud.start_time::time, ud.end_time::time)
(我用user_name
了代替user
,因为user
是保留关键字)
请注意,加入使用要求以与返回它to_char(ud.start_time, 'FMday') = lower(pi.week_day)
相同的语言存储工作日。to_char()
最好将其存储为数字,而不是字符串。
有了这个结果,就可以计算出每个节目的实际开始和结束时间。这可以通过一个复杂的语句来完成,该case when
语句将存储的时间信息usage_detail
与program_info
检查哪个开始时间较大以及哪个结束时间较小的时间信息进行比较。
然而,这可以使用时间范围来简化。不幸的是,没有内置这样的范围时间,但很容易创建:
create type timerange as range (subtype = time);
这样,可以使用两个范围的交集来计算实际的开始时间和结束时间:
select ud.user_name,
pi.program_id,
pi.program_category,
ud.start_time::date as start_day,
timerange(pi.start_time, pi.end_time) * timerange(ud.start_time::time, ud.end_time::time) as view_interval
from program_info pi
join usage_detail ud
on to_char(ud.start_time, 'FMday') = lower(pi.week_day)
and (pi.start_time, pi.end_time) overlaps (ud.start_time::time, ud.end_time::time)
*
是范围的交集运算符。以上返回:
user_name | program_id | program_category | start_day | view_interval
----------+------------+------------------+------------+--------------------
A | 1 | News | 2016-10-31 | [13:15:00,13:30:00)
A | 2 | Sports | 2016-10-31 | [13:30:00,14:25:00)
将实际观看时间作为一个范围现在可用于获得您想要的最终显示:
with view_times as (
select ud.user_name,
pi.program_id,
pi.program_category,
ud.start_time::date as start_day,
timerange(pi.start_time, pi.end_time) * timerange(ud.start_time::time, ud.end_time::time) as view_interval
from program_info pi
join usage_detail ud
on to_char(ud.start_time, 'FMday') = lower(pi.week_day)
and (pi.start_time, pi.end_time) overlaps (ud.start_time::time, ud.end_time::time)
)
select user_name, program_id, program_category,
start_day + lower(view_interval) as actual_start_time,
extract(epoch from (upper(view_interval) - lower(view_interval))) as duration
from view_times
这将返回:
user_name | program_id | program_category | actual_start_time | duration
----------+------------+------------------+---------------------+---------
A | 1 | News | 2016-10-31 13:15:00 | 900
A | 2 | Sports | 2016-10-31 13:30:00 | 3300
在线示例:http ://rextester.com/VNXIG64065