我有一个plpgsql函数,它根据名为timeslots
的表中存储的规则在两个日期之间生成TSTZRANGE。它工作正常,但现在我得到了一个新的要求,并在datespan
表中添加了一个名为timeslots
的TSTZRANGE字段,我还需要对其进行过滤,以便只返回此字段值中包含的范围。
在这里展示我需要改变的部分功能。 eid
,fromdate
和todate
是传递给函数的参数。
SELECT TSTZRANGE(
(series::DATE + ts1.start)::TIMESTAMPTZ AT TIME ZONE 'UTC',
(series::DATE + ts1.end)::TIMESTAMPTZ AT TIME ZONE 'UTC'
) AS range
FROM
timeslots AS ts1,
generate_series(fromdate, todate, '1 day') AS series
WHERE
eid = ts1.event_id AND
EXTRACT(DOW FROM series) = ANY(ts1.weekdays)
ORDER BY
range
所以我想要做的是添加一个像WHERE range <@ ts1.datespan
这样的过滤器,但我无法将它放在任何可行的地方。
实施例:
在timeslots
表中提供此信息:
id | start | end | weekdays | event_id | datespan
----+----------+----------+---------------+----------------------------------------------------------------
1 | 12:00:00 | 14:00:00 | {1,2,3,5,6,0} | 1 | ["2017-01-01 00:00:00+00","2017-02-01 00:00:00+00")
2 | 09:00:00 | 11:00:00 | {1,2,3,5,6,0} | 1 | [null, null)
3 | 15:00:00 | 17:00:00 | {1,2,3,5,6,0} | 1 | ["2017-02-01 00:00:00+00","2017-03-01 00:00:00+00")
如果eid=1
,fromdate='2017-02-02'
和todate='2017-02-03'
如下所示,则调用上面的SELECT的结果如下:
range
-----------------------------------------------------
["2017-02-02 09:00:00+00","2017-02-02 11:00:00+00")
["2017-02-02 15:00:00+00","2017-02-02 17:00:00+00")
["2017-02-03 09:00:00+00","2017-02-03 11:00:00+00")
["2017-02-03 15:00:00+00","2017-02-03 17:00:00+00")
答案 0 :(得分:1)
最简单的方法是使用lateral
:
LATERAL关键字可以在子SELECT FROM项之前。这允许子SELECT引用FROM列表中出现在它之前的FROM项列。 (如果没有LATERAL,每个子SELECT都是独立评估的,因此不能交叉引用任何其他FROM项。)
select ts1.*, range
from
timeslots as ts1,
generate_series('2017-02-02'::date, '2017-02-03', '1 day') as series
cross join lateral
(
select tstzrange (
(series::date + ts1.start)::timestamptz at time zone 'utc',
(series::date + ts1.end)::timestamptz at time zone 'utc'
) as range
) range
where
1 = ts1.event_id and
extract(dow from series) = any(ts1.weekdays) and
range <@ ts1.datespan
order by range
;
id | start | end | weekdays | event_id | datespan | range
----+----------+----------+---------------+----------+-----------------------------------------------------+-----------------------------------------------------
2 | 09:00:00 | 11:00:00 | {1,2,3,5,6,0} | 1 | (,) | ["2017-02-03 09:00:00+00","2017-02-03 11:00:00+00")
3 | 15:00:00 | 17:00:00 | {1,2,3,5,6,0} | 1 | ["2017-02-01 00:00:00+00","2017-03-01 00:00:00+00") | ["2017-02-03 15:00:00+00","2017-02-03 17:00:00+00")
另一种方法是将其包装在外部查询中。现在您需要决定/告知如何处理空边界。